Bir dosyadaki bir dizgiyi nasıl değiştirebilirim?


752

Dosyalarda dizgileri belirli arama kriterlerine göre değiştirmek çok yaygın bir iştir. Nasıl yapabilirim

  • Geçerli dizindeki tüm dosyalarda dize fooile değiştirilsin barmi?
  • alt dizinler için özyinelemeli olarak aynı mı?
  • yalnızca dosya adı başka bir dizeyle eşleşirse değiştirilsin mi?
  • Sadece dize belirli bir bağlamda bulunursa değiştirin?
  • dize belirli bir satır numarasındaysa değiştirilsin mi?
  • aynı yerine birden çok dizeyi koy
  • Birden çok dizgiyi farklı yerine yerleştirme

2
Bu, konuyla ilgili kanonik bir soru ve cevap niteliğindedir (bu meta tartışmaya bakın ).
terdon

Yanıtlar:


1010

1. Geçerli dizindeki tüm dosyalarda bir dizgenin tüm oluşumlarını bir başkasıyla değiştirmek:

Bunlar , dizinin yalnızca normal dosyalar içerdiğini ve tüm gizli olmayan dosyaları işlemek istediğinizi bildiğiniz durumlar içindir. Aksi takdirde, yaklaşımları 2'de kullanın.

sedBu cevaptaki tüm çözümler GNU’yu varsaymaktadır sed. FreeBSD ya da OS / X kullanıyorsanız, yerine -iile -i ''. Ayrıca, -ianahtarın herhangi bir sürümüyle kullanımının sed, belirli dosya sistemi güvenliği etkilerinin olduğunu ve herhangi bir şekilde dağıtmayı planladığınız herhangi bir komut dosyasında görünmez olduğunu unutmayın.

  • Özyinelemeli değil, sadece bu dizindeki dosyalar:

    sed -i -- 's/foo/bar/g' *
    perl -i -pe 's/foo/bar/g' ./* 

    ( perlbiri biten |veya boşluk biten dosya isimleri için başarısız olur ) ).

  • Bu ve tüm alt dizinlerde özyinelemeli, düzenli dosyalar ( gizli olanlar dahil )

    find . -type f -exec sed -i 's/foo/bar/g' {} +

    Eğer zsh kullanıyorsanız:

    sed -i -- 's/foo/bar/g' **/*(D.)

    (liste çok büyükse başarısız olabilir, zargsçalışmayı görün).

    Bash normal dosyaları doğrudan kontrol edemez, bir döngü gereklidir (parantez seçenekleri genel olarak ayarlamaktan kaçınır):

    ( shopt -s globstar dotglob;
        for file in **; do
            if [[ -f $file ]] && [[ -w $file ]]; then
                sed -i -- 's/foo/bar/g' "$file"
            fi
        done
    )

    Dosyalar gerçek dosyalar (-f) olduğunda ve yazılabilir (-w) olduğunda seçilir.

2. Yalnızca dosya adı başka bir dizeyle eşleşiyorsa / belirli bir uzantıya sahipse / belirli türde bir vb ise değiştirin:

  • Özyinelemeli olmayan, sadece bu dizindeki dosyalar:

    sed -i -- 's/foo/bar/g' *baz*    ## all files whose name contains baz
    sed -i -- 's/foo/bar/g' *.baz    ## files ending in .baz
  • Bu ve tüm alt dizinlerde özyinelemeli, düzenli dosyalar

    find . -type f -name "*baz*" -exec sed -i 's/foo/bar/g' {} +

    Bash kullanıyorsanız (kaşlı ayraçlar, seçenekleri genel olarak ayarlamaktan kaçının):

    ( shopt -s globstar dotglob
        sed -i -- 's/foo/bar/g' **baz*
        sed -i -- 's/foo/bar/g' **.baz
    )

    Eğer zsh kullanıyorsanız:

    sed -i -- 's/foo/bar/g' **/*baz*(D.)
    sed -i -- 's/foo/bar/g' **/*.baz(D.)

    Daha fazla bayrak komut satırında verilmeyeceğini --söylemeye yarar sed. Bu, ile başlayan dosya adlarına karşı koruma sağlamak için kullanışlıdır -.

  • Bir dosya belirli bir türde ise, örneğin çalıştırılabilir ( man finddaha fazla seçenek için bakınız ):

    find . -type f -executable -exec sed -i 's/foo/bar/g' {} +

    zsh:

    sed -i -- 's/foo/bar/g' **/*(D*)

3. Yalnızca dizenin belirli bir bağlamda bulunması durumunda değiştirin.

  • Aynı satırda daha sonra varsa, fooile değiştirin :barbaz

    sed -i 's/foo\(.*baz\)/bar\1/' file

    İçinde sed, \( \)parantez içinde ne varsa onu kaydeder ve daha sonra erişebilirsiniz \1. Bu konunun düzenli ifadeleri hakkında daha fazla bilgi edinmek için, bu temanın birçok çeşidi vardır, buraya bakınız .

  • Yerine fooile baryalnızca foogiriş dosyasının 3d sütunu (alan) bulunur (boşluk ile ayrılmış alanları varsayılarak):

    gawk -i inplace '{gsub(/foo/,"baz",$3); print}' file

    ( gawk4.1.0 veya daha yenisine ihtiyaç duyuyor ).

  • Farklı alan için sadece kullanmak $Nnerede Nilgi alanına sayısıdır. Farklı bir alan ayırıcı için ( :bu örnekte) şunları kullanın:

    gawk -i inplace -F':' '{gsub(/foo/,"baz",$3);print}' file

    Başka bir çözüm kullanarak perl:

    perl -i -ane '$F[2]=~s/foo/baz/g; $" = " "; print "@F\n"' foo 

    NOT: Her iki awkve perlçözeltiler dosyasında aralık etkiler (ön ve arka boşlukları kaldırma ve uygun çizgilerde de bir boşluk karakteri için boşlukları dizileri) dönüştürmek olacaktır. Farklı bir alan için, istediğiniz alan numarasının $F[N-1]nerede Nolduğunu ve farklı bir alan ayırıcı kullanımı için kullanın ( $"=":"çıkış alan ayırıcısını ayarlar :):

    perl -i -F':' -ane '$F[2]=~s/foo/baz/g; $"=":";print "@F"' foo 
  • Değiştir fooile barsadece 4 hat üzerinde:

    sed -i '4s/foo/bar/g' file
    gawk -i inplace 'NR==4{gsub(/foo/,"baz")};1' file
    perl -i -pe 's/foo/bar/g if $.==4' file

4. Çoklu değiştirme işlemleri: farklı dizelerle değiştirin

  • sedKomutları birleştirebilirsiniz :

    sed -i 's/foo/bar/g; s/baz/zab/g; s/Alice/Joan/g' file

    Sipariş konularda (unutmayın sed 's/foo/bar/g; s/bar/baz/g'ikame edecektir fooile baz).

  • veya Perl komutları

    perl -i -pe 's/foo/bar/g; s/baz/zab/g; s/Alice/Joan/g' file
  • Çok sayıda desene sahipseniz, desenlerinizi ve bunların değiştirmelerini bir sedkomut dosyasına kaydetmek kolaydır :

    #! /usr/bin/sed -f
    s/foo/bar/g
    s/baz/zab/g
  • Veya, yukarıdakiler için uygun olması için çok sayıda desen çiftiniz varsa, desen çiftlerini bir dosyadan okuyabilirsiniz (iki boşlukla ayrılmış desen, $ desen ve satır başına $ değiştirme):

    while read -r pattern replacement; do   
        sed -i "s/$pattern/$replacement/" file
    done < patterns.txt
  • Uzun kalıp listeleri ve büyük veri dosyaları için bu oldukça yavaştır; bu nedenle kalıpları okumak ve sedonlardan bir betik oluşturmak isteyebilirsiniz . Aşağıdaki, bir <space> sınırlayıcısının , dosyada satır başına bir tane oluşan MATCH <boşluk> REPLACE çiftlerinin bir listesini ayırdığını varsayar patterns.txt:

    sed 's| *\([^ ]*\) *\([^ ]*\).*|s/\1/\2/g|' <patterns.txt |
    sed -f- ./editfile >outfile

    Yukarıdaki biçimi örneğin bir izin vermez, büyük ölçüde keyfi ve <boşluk> biriyle MATCH veya DEĞİŞTİRİN . Yöntem çok genel olsa da: temel olarak, bir sedbetiğe benzeyen bir çıktı akışı oluşturabilirseniz , o zaman o dizeyi betiğini stdin olarak sedbelirterek bir betiği sedolarak kaynaklayabilirsiniz -.

  • Birden çok komut dosyasını benzer şekilde birleştirebilir ve birleştirebilirsiniz:

    SOME_PIPELINE |
    sed -e'#some expression script'  \
        -f./script_file -f-          \
        -e'#more inline expressions' \
    ./actual_edit_file >./outfile

    Bir POSIX sed, tüm komut dosyalarını komut satırında göründükleri sırayla birleştirir. Bunların hiçbiri bir \nsatırda bitmiyor.

  • grep aynı şekilde çalışabilir:

    sed -e'#generate a pattern list' <in |
    grep -f- ./grepped_file
  • Sabit dizelerle desen olarak çalışırken, düzenli ifade meta karakterlerinden kaçmak iyi bir uygulamadır . Bunu kolayca yapabilirsiniz:

    sed 's/[]$&^*\./[]/\\&/g
         s| *\([^ ]*\) *\([^ ]*\).*|s/\1/\2/g|
    ' <patterns.txt |
    sed -f- ./editfile >outfile

5. Birden çok değiştirme işlemi: aynı dizeyle birden çok deseni değiştirme

  • Herhangi değiştirin foo, barya da bazbirliktefoobar

    sed -Ei 's/foo|bar|baz/foobar/g' file
  • veya

    perl -i -pe 's/foo|bar|baz/foobar/g' file

2
@ StéphaneChazelas düzenleme için teşekkürler, gerçekten birkaç şeyi düzeltti. Ancak, lütfen bash ile ilgili bilgileri çıkarmayın. Herkes kullanmaz zsh. Elbette, zshbilgi ekle, ancak bash şeyler kaldırmak için hiçbir sebep yoktur. Ayrıca, kabuğun metin işlemesi için kullanılmasının ideal olmadığını, ancak ihtiyaç duyulan durumlar olduğunu biliyorum. Özgün komut dosyamın daha iyi bir sürümünde, sedayrıştırmak için kabuk döngüsünü kullanmak yerine bir komut dosyası oluşturacak şekilde düzenledim . Bu, örneğin birkaç yüz çift düzeniniz varsa faydalı olabilir.
terdon

2
@ terdon, bash'ınız yanlış. 4.3'ten önceki bash, alçalırken sembolik izleri takip edecektir. Ayrıca, bash, (.)globbing niteleyicisine eşdeğerde olmadığı için burada kullanılamaz. (biraz özlüyorsun - aynı zamanda). For döngüsü yanlıştır (eksik -r) ve dosyalarda birkaç geçiş yapmak anlamına gelir ve bir sed betiğin hiçbir faydası olmaz.
Stéphane Chazelas,

7
@ terdon substitute komutundan önce ve --sonra ne sed -igösterir?
Geek

5
@Geek bu bir POSIX olayı. Seçeneklerin sonunu belirtir ve ile başlayan argümanları iletmenizi sağlar -. Bunu kullanmak, komutların, benzer adlara sahip dosyalar üzerinde çalışmasını sağlar -foo. O olmadan, -fseçenek olarak ayrıştırılırdı.
terdon

1
Özyinelemeli komutların bazılarını git depolarında uygularken çok dikkatli olun. Örneğin, bu cevabın 1. bölümünde verilen çözümler, aslında bir .gitdizindeki dahili git dosyalarını değiştirecek ve gerçekten ödemenizi mahvedecektir. Belirli dizinlerde / içinde isimlerle çalışmak daha iyidir.
Pistos

75

İyi r e pl acement Linux aracıdır rpl onunla kullanılabilir böylece başlangıçta, Debian projesi için yazılmıştır, apt-get install rplherhangi Debian türevi dağıtıma içinde, ve diğerleri için olabilir, ama aksi takdirde indirebilirsiniz tar.gzdosyayı SourgeForge .

En basit kullanım örneği:

 $ rpl old_string new_string test.txt

Dize boşluklar içeriyorsa, tırnak işaretleri içine alınmalıdır. Varsayılan olarak rpl, büyük harflere dikkat edin , ancak kelimelerin tamamı için değil , ancak bu varsayılanları seçeneklerle -i(büyük / küçük harf yoksay) ve -w(tam kelimeler) değiştirebilirsiniz. Ayrıca birden fazla dosya belirleyebilirsiniz :

 $ rpl -i -w "old string" "new string" test.txt test2.txt

Hatta belirtmek uzantıları ( -xarama bile arama ya kadar) yinelemeli ( -Rdizininde):

 $ rpl -x .html -x .txt -R old_string new_string test*

Ayrıca yerine / arama yapabilirsiniz interaktif modda ile -p(istemi) seçeneği:

Çıktı, değiştirilen dosyaların / dizginin sayısını ve arama türünü (küçük / büyük / küçük / büyük / küçük harf olarak) gösterir, ancak -q( sessiz mod ) seçeneğiyle sessiz olabilir veya içeren satır numaralarını listeleyen daha ayrıntılı her bir dosya ve dizinin -v( ayrıntılı mod ) seçeneği ile eşleşmesini sağlar .

Hatırlamaya değer diğer seçeneklerdir -e(namus e izin scapes) regular expressions, bu nedenle de sekmeleri (arama yapabilirsiniz \t), yeni hatlar ( \nvs). Hatta izinleri zorlamak-f için de kullanabilirsiniz (elbette, yalnızca kullanıcı yazma izinlerine sahipse) ve değişiklik zamanlarını korumak için `.-d

Son olarak, hangisinden tam olarak hangisi yapacağınızdan emin değilseniz, -s( benzetme modunu ) kullanın.


2
Geri bildirimde ve sadelikte sed'den çok daha iyi. Keşke dosya isimlerine göre hareket etmesine izin verseydi, ve sonra olduğu gibi mükemmel olurdu.
Kzqai,

1
-s (benzetme modu) :-)
erm3nda

25

Bir arama yapıp birden fazla dosya üzerinde değişiklik yapılmasını önerir:

Ayrıca find ve sed komutunu da kullanabilirsiniz, ancak bu küçük perl dizisinin iyi çalıştığını biliyorum.

perl -pi -w -e 's/search/replace/g;' *.php
  • -e, aşağıdaki kod satırını çalıştırmak anlamına gelir.
  • -i yerinde düzenlemek anlamına gelir
  • -w uyarıları yazmak
  • -p Giriş dosyası üzerinde döngü, komut dosyası uygulandıktan sonra her satırı yazdırma.

En iyi sonuçlarım perl ve grep kullanmaktan kaynaklanıyor (dosyanın arama ifadesine sahip olmasını sağlamak için)

perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )

13

Vim'i Ex modunda kullanabilirsiniz:

Geçerli dizindeki tüm dosyalarda ALF dizesini BRA ile değiştirilsin mi?

for CHA in *
do
  ex -sc '%s/ALF/BRA/g' -cx "$CHA"
done

alt dizinler için özyinelemeli olarak aynı mı?

find -type f -exec ex -sc '%s/ALF/BRA/g' -cx {} ';'

yalnızca dosya adı başka bir dizeyle eşleşirse değiştirilsin mi?

for CHA in *.txt
do
  ex -sc '%s/ALF/BRA/g' -cx "$CHA"
done

Sadece dize belirli bir bağlamda bulunursa değiştirin?

ex -sc 'g/DEL/s/ALF/BRA/g' -cx file

dize belirli bir satır numarasındaysa değiştirilsin mi?

ex -sc '2s/ALF/BRA/g' -cx file

aynı yerine birden çok dizeyi koy

ex -sc '%s/\vALF|ECH/BRA/g' -cx file

Birden çok dizgiyi farklı yerine yerleştirme

ex -sc '%s/ALF/BRA/g|%s/FOX/GOL/g' -cx file

13

Bunu kullandım:

grep -r "old_string" -l | tr '\n' ' ' | xargs sed -i 's/old_string/new_string/g'
  1. İçerdiği tüm dosyaları listele old_string.

  2. Sonuç olarak yeni satırı boşluklar ile değiştirin (böylece dosyaların listesi beslenebilir sed.

  3. sedEski dizgiyi yenisiyle değiştirmek için bu dosyalarda çalıştırın .

Güncelleme: Yukarıdaki sonuç, boşluk içeren dosya adlarında başarısız olur. Bunun yerine kullanın:

grep --null -lr "old_string" | xargs --null sed -i 's/old_string/new_string/g'


Dosya adlarınızdan herhangi biri boşluk, sekme veya yeni satır içeriyorsa, bunun başarısız olacağını unutmayın. Kullanım grep --null -lr "old_string" | xargs --null sed -i 's/old_string/new_string/g', rasgele dosya adları ile ilgilenmesini sağlar.
terdon

teşekkürler beyler. güncelleme eklendi ve eski kodu bıraktı, çünkü bu davranıştan haberi olmayan biri için faydalı olabilecek ilginç bir uyarı.
o_o_o--

6

Bir kullanıcının bakış açısından, işi mükemmel yapan hoş ve basit bir Unix aracıdır qsubst. Örneğin,

% qsubst foo bar *.c *.h

yerini alacak fooolan bartüm C dosyalarında. Güzel bir özellik, qsubstbir sorgu değiştirme işlemi yapmasıdır , yani bana her oluşumunu gösterecek foove değiştirmek isteyip istemediğimi soracaktır. [Koşulsuz olarak (soran yok) -goseçeneğiyle değiştirebilir ve örneğin -wyalnızca footam bir sözcük olduğunda değiştirmek isterseniz , başka seçenekler de olabilir .]

Nasıl elde edilir: qsubstder Mouse (McGill'den) tarafından icat edildi ve Ağustos 1987'de comp.unix.sources 11 (7) 'ye gönderildi. Güncelleme sürümleri mevcut. Örneğin, NetBSD sürümü qsubst.c,v 1.8 2004/11/01mac'umda mükemmel şekilde derleniyor ve çalışıyor.


2

Ben kuru işletilen seçeneği sağlayacak ve bir topak ile yinelemeli çalışacak ve bunu yapmaya çalışıyor sonra bir şey gerekiyordu awkve sedben vazgeçti ve bunun yerine piton yaptım.

Komut Bir gıdım deseni (örneğin eşleştirme yinelemeli tüm dosyaları arar --glob="*.html"bir regex için) ve yedek regex ile yerine geçer:

find_replace.py [--dir=my_folder] \
    --search-regex=<search_regex> \
    --replace-regex=<replace_regex> \
    --glob=[glob_pattern] \
    --dry-run

Örneğin, her uzun seçeneğin --search-regexkarşılık gelen kısa bir seçeneği vardır -s. -hTüm seçenekleri görmek için ile çalıştırın .

Örneğin, bu gelen tüm tarihleri çevirecek 2017-12-31için 31-12-2017:

python replace.py --glob=myfile.txt \
    --search-regex="(\d{4})-(\d{2})-(\d{2})" \
    --replace-regex="\3-\2-\1" \
    --dry-run --verbose
import os
import fnmatch
import sys
import shutil
import re

import argparse

def find_replace(cfg):
    search_pattern = re.compile(cfg.search_regex)

    if cfg.dry_run:
        print('THIS IS A DRY RUN -- NO FILES WILL BE CHANGED!')

    for path, dirs, files in os.walk(os.path.abspath(cfg.dir)):
        for filename in fnmatch.filter(files, cfg.glob):

            if cfg.print_parent_folder:
                pardir = os.path.normpath(os.path.join(path, '..'))
                pardir = os.path.split(pardir)[-1]
                print('[%s]' % pardir)
            filepath = os.path.join(path, filename)

            # backup original file
            if cfg.create_backup:
                backup_path = filepath + '.bak'

                while os.path.exists(backup_path):
                    backup_path += '.bak'
                print('DBG: creating backup', backup_path)
                shutil.copyfile(filepath, backup_path)

            with open(filepath) as f:
                old_text = f.read()

            all_matches = search_pattern.findall(old_text)

            if all_matches:

                print('Found {} matches in file {}'.format(len(all_matches), filename))

                new_text = search_pattern.sub(cfg.replace_regex, old_text)

                if not cfg.dry_run:
                    with open(filepath, "w") as f:
                        print('DBG: replacing in file', filepath)
                        f.write(new_text)
                else:
                    for idx, matches in enumerate(all_matches):
                        print("Match #{}: {}".format(idx, matches))

                    print("NEW TEXT:\n{}".format(new_text))

            elif cfg.verbose:
                print('File {} does not contain search regex "{}"'.format(filename, cfg.search_regex))


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='''DESCRIPTION:
    Find and replace recursively from the given folder using regular expressions''',
                                     formatter_class=argparse.RawDescriptionHelpFormatter,
                                     epilog='''USAGE:
    {0} -d [my_folder] -s <search_regex> -r <replace_regex> -g [glob_pattern]

    '''.format(os.path.basename(sys.argv[0])))

    parser.add_argument('--dir', '-d',
                        help='folder to search in; by default current folder',
                        default='.')

    parser.add_argument('--search-regex', '-s',
                        help='search regex',
                        required=True)

    parser.add_argument('--replace-regex', '-r',
                        help='replacement regex',
                        required=True)

    parser.add_argument('--glob', '-g',
                        help='glob pattern, i.e. *.html',
                        default="*.*")

    parser.add_argument('--dry-run', '-dr',
                        action='store_true',
                        help="don't replace anything just show what is going to be done",
                        default=False)

    parser.add_argument('--create-backup', '-b',
                        action='store_true',
                        help='Create backup files',
                        default=False)

    parser.add_argument('--verbose', '-v',
                        action='store_true',
                        help="Show files which don't match the search regex",
                        default=False)

    parser.add_argument('--print-parent-folder', '-p',
                        action='store_true',
                        help="Show the parent info for debug",
                        default=False)

    config = parser.parse_args(sys.argv[1:])

    find_replace(config)

Here betiğin arama terimlerini ve değiştirmelerini farklı renklerle vurgulayan güncellenmiş bir sürümüdür.


1
Neden bu kadar karmaşık bir şey yaptığını anlamıyorum. Özyineleme için, bash'in (veya kabuğunuzun eşdeğeri) globstarseçeneğini ve **glob'ları veya kullanın find. Kuru çalışma için, sadece kullanmak sed. Bu -iseçeneği kullanmazsanız, herhangi bir değişiklik yapmaz. Yedek bir kullanım için sed -i.bak(veya perl -i .bak); eşleşmeyen dosyalar için kullanın grep PATTERN file || echo file. Ve neden dünyada python'un kabuğunu yapmasına izin vermek yerine globu genişletmesini istiyorsunuz? Neden script.py --glob=foo*sadece script.py foo*?
Terdon

1
Benim neden çok basit: (1) her şeyden önce, hata ayıklama kolaylığı; (2) destekleyici bir topluluğa sahip sadece iyi belgelenmiş bir araç kullanarak (3) bilmeyen sedve awkiyi bildikleri ve onlara hakim olmak için fazladan zaman ayırmaya istekli olmadıkları , (4) okunabilirlik, (5) bu çözüm posix olmayan sistemlerde de çalışacaktır (buna ihtiyacım olduğu değil ama başkası olabilir).
ccpizza

1

ripgrep (komut adı rg) bir greparaçtır, fakat aynı zamanda aramayı ve değiştirmeyi de destekler.

$ cat ip.txt
dark blue and light blue
light orange
blue sky
$ # by default, line number is displayed if output destination is stdout
$ # by default, only lines that matched the given pattern is displayed
$ # 'blue' is search pattern and -r 'red' is replacement string
$ rg 'blue' -r 'red' ip.txt
1:dark red and light red
3:red sky

$ # --passthru option is useful to print all lines, whether or not it matched
$ # -N will disable line number prefix
$ # this command is similar to: sed 's/blue/red/g' ip.txt
$ rg --passthru -N 'blue' -r 'red' ip.txt
dark red and light red
light orange
red sky


rg yerinde seçeneği desteklemediğinden, kendiniz yapmak zorunda kalacaksınız

$ # -N isn't needed here as output destination is a file
$ rg --passthru 'blue' -r 'red' ip.txt > tmp.txt && mv tmp.txt ip.txt
$ cat ip.txt
dark red and light red
light orange
red sky


Düzenli ifade sözdizimi ve özellikleri için Rust regex belgelerine bakın . -PAnahtar sağlayacak PCRE2 lezzet. rgVarsayılan olarak Unicode'u destekler.

$ # non-greedy quantifier is supported
$ echo 'food land bark sand band cue combat' | rg 'foo.*?ba' -r 'X'
Xrk sand band cue combat

$ # unicode support
$ echo 'fox:αλεπού,eagle:αετός' | rg '\p{L}+' -r '($0)'
(fox):(αλεπού),(eagle):(αετός)

$ # set operator example, remove all punctuation characters except . ! and ?
$ para='"Hi", there! How *are* you? All fine here.'
$ echo "$para" | rg '[[:punct:]--[.!?]]+' -r ''
Hi there! How are you? All fine here.

$ # use -P if you need even more advanced features
$ echo 'car bat cod map' | rg -P '(bat|map)(*SKIP)(*F)|\w+' -r '[$0]'
[car] bat [cod] map


Gibi grep, -Fseçenek sabit dizeleri eşleşmesini sağlayacak, ben sedde uygulamak gerektiğini düşündüğüm kullanışlı bir seçenek .

$ printf '2.3/[4]*6\nfoo\n5.3-[4]*9\n' | rg --passthru -F '[4]*' -r '2'
2.3/26
foo
5.3-29


Başka bir seçenek de -Uçok satırlı eşleştirmeyi mümkün kılmak

$ # (?s) flag will allow . to match newline characters as well
$ printf '42\nHi there\nHave a Nice Day' | rg --passthru -U '(?s)the.*ice' -r ''
42
Hi  Day


rg dos tarzı dosyaları da kaldırabilir

$ # same as: sed -E 's/\w+(\r?)$/123\1/'
$ printf 'hi there\r\ngood day\r\n' | rg --passthru --crlf '\w+$' -r '123'
hi 123
good 123


Bir başka avantajı ise rgdaha hızlı olması muhtemeldirsed

$ # for small files, initial processing time of rg is a large component
$ time echo 'aba' | sed 's/a/b/g' > f1
real    0m0.002s
$ time echo 'aba' | rg --passthru 'a' -r 'b' > f2
real    0m0.007s

$ # for larger files, rg is likely to be faster
$ # 6.2M sample ASCII file
$ wget https://norvig.com/big.txt    
$ time LC_ALL=C sed 's/\bcat\b/dog/g' big.txt > f1
real    0m0.060s
$ time rg --passthru '\bcat\b' -r 'dog' big.txt > f2
real    0m0.048s
$ diff -s f1 f2
Files f1 and f2 are identical

$ time LC_ALL=C sed -E 's/\b(\w+)(\s+\1)+\b/\1/g' big.txt > f1
real    0m0.725s
$ time rg --no-pcre2-unicode --passthru -wP '(\w+)(\s+\1)+' -r '$1' big.txt > f2
real    0m0.093s
$ diff -s f1 f2
Files f1 and f2 are identical
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.