Komutları kullanarak dosya içindeki metni bulma ve değiştirme

Komut satırını kullanarak bir metin dosyasındaki belirli kelimeleri nasıl bulabilir ve değiştirebilirim?

sed -i 's/original/new/g' file.txt

Açıklama:

  • sed = Akış Düzenleyicisi
  • -i = yerinde (yani orijinal dosyaya geri kaydet)
  • Komut dizesi:

    • s = yedek komut
    • original = değiştirilecek sözcüğü (veya yalnızca sözcüğün kendisini) açıklayan normal ifade
    • new = değiştirilecek metin
    • g = global (yani, yalnızca ilk oluşumu değil, tümünü değiştirin)
  • file.txt = dosya adı

Bunu başarmak için yolları çok sayıda var. Dize değiştirme ile elde etmeye çalışılanın karmaşıklığına ve kullanıcının aşina olduğu araçlara bağlı olarak, bazı yöntemler diğerlerinden daha fazla tercih edilebilir.

Bu cevapta basit kullanıyorum input.txt burada verilen tüm örnekleri test etmek için kullanabileceğiniz dosya. Dosya içeriği:

roses are red , violets are blueThis is an input.txt and this doesn't rhyme

DENEME

Bash gerçekten metin işleme için tasarlanmamıştır, ancak basit değiştirmeler şu yollarla yapılabilir parametre genişletme özellikle burada basit bir yapı kullanabiliriz ${parameter/old_string/new_string}.

#!/bin/bashwhile IFS= read -r linedo    case "$line" in       *blue*) printf "%s\n" "${line/blue/azure}" ;;       *) printf "%s\n" "$line" ;;    esacdone < input.txt

Bu küçük komut dosyası yerinde değiştirme yapmaz, yani yeni metni yeni dosyaya kaydetmeniz ve eski dosyadan kurtulmanız veya mv new.txt old.txt

Yan not: nedenini merak ediyorsanız while IFS= read -r ; do ... done < input.txt kullanılır, temel olarak shell'in dosyayı satır satır okuma şeklidir. Görmek bu referans için.

AWK

AWK, bir metin işleme yardımcı programı olarak, bu görev için oldukça uygundur. Basit değiştirmeler ve çok daha gelişmiş olanları temel alabilir düzenli ifadeler. İki işlev sağlar: sub() ve gsub(). İlki yalnızca ilk oluşumun yerini alırken, ikincisi - tüm dizedeki oluşumların yerini alır. Örneğin, dizemiz varsa one potato two potato , bu sonuç olacaktır:

$ echo "one potato two potato" | awk '{gsub(/potato/,"banana")}1'one banana two banana$ echo "one potato two potato" | awk '{sub(/potato/,"banana")}1'                                      one banana two potato 

AWK bir girdi dosyasını argüman olarak alabilir, bu yüzden aynı şeyleri yapar input.txt olur olmak kolay:

awk '{sub(/blue/,"azure")}1' input.txt

Sahip olduğunuz AWK sürümüne bağlı olarak, yerinde düzenlemeye sahip olabilir veya olmayabilir, bu nedenle normal uygulama yeni metni kaydetmek ve değiştirmektir. Örneğin böyle bir şey:

awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt

SED

Sed bir çizgi editörüdür. Aynı zamanda normal ifadeler kullanır, ancak basit değiştirmeler için bunu yapmak yeterlidir:

sed 's/blue/azure/' input.txt

Bu araçla ilgili en iyi şey, etkinleştirebileceğiniz yerinde düzenlemeye sahip olmasıdır -i bayrak.

Perlname

Perl, metin işleme için sıklıkla kullanılan başka bir araçtır, ancak genel amaçlı bir dildir ve ağ oluşturma, sistem yönetimi, masaüstü uygulamaları ve diğer birçok yerde kullanılır. C, sed, awk ve diğerleri gibi diğer dillerden birçok kavram / özellik ödünç aldı. Basit ikame şu şekilde yapılabilir:

perl -pe 's/blue/azure/' input.txt

Sed gibi, perl de -ı bayrağına sahiptir.

Piton

Bu dil çok yönlüdür ve çok çeşitli uygulamalarda da kullanılır. Dizelerle çalışmak için birçok işlevi vardır, bunların arasında replace() yani eğer değişkeniniz varsa var="Hello World" olabilir misin var.replace("Hello","Good Morning")

Dosyayı okumak ve içindeki dizeyi değiştirmek için basit bir yol şöyle olurdu:

python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt

Bununla birlikte, Python ile, komut dosyasının içinden de yapabileceğiniz yeni bir dosyaya da çıkmanız gerekir. Örneğin, işte basit bir tane:

#!/usr/bin/env pythonimport sysimport osimport tempfiletmp=tempfile.mkstemp()with open(sys.argv[1]) as fd1, open(tmp[1],'w') as fd2:    for line in fd1:        line = line.replace('blue','azure')        fd2.write(line)os.rename(tmp[1],sys.argv[1])

Bu komut dosyası ile çağrılacak input.txt komut satırı argümanı olarak. Python betiğini komut satırı argümanı ile çalıştırmak için tam komut şöyle olacaktır

 $ ./myscript.py input.txt

veya

$ python ./myscript.py input.txt

Tabii ki, emin olun ./myscript.py geçerli çalışma dizininizdedir ve ilk olarak, çalıştırılabilir olarak ayarlandığından emin olun chmod +x ./myscript.py

Python ayrıca düzenli ifadelere de sahip olabilir, özellikle re sahip olduğu modül re.sub() daha gelişmiş değiştirmeler için kullanılabilen işlev.

Bunu yapmanın birçok farklı yolu vardır. Bunlardan biri kullanıyor sed ve Regex. SED, metni filtrelemek ve dönüştürmek için kullanılan bir Akış Düzenleyicisidir. Bir örnek aşağıdaki gibidir:

marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orlymarco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarlymarco@imacs-suck: ~$ cat yarlyThe quick brown unicorn jumped over the hyper sleeping dog

Bundan daha mantıklı olabilecek başka bir yol < strin ve > strout borularla!

marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowaimarco@imacs-suck: ~$ cat nowai The quick brown fox jumped over the lazy sleeping dog

Awk'nin gsub komutuyla,

awk '{gsub(/pattern/,"replacement")}' file

Örnek:

awk '{gsub(/1/,"0");}' file

Yukarıdaki örnekte, bulunduğu sütundan bağımsız olarak tüm 1'ler 0'larla değiştirilir.


Belirli bir sütunda değiştirme yapmak istiyorsanız, bunu yapın,

awk '{gsub(/pattern/,"replacement",column_number)}' file

Örnek:

awk '{gsub(/1/,"0",$1);}' file

Yalnızca ilk sütunda 1'i 0 ile değiştirir.

Perl aracılığıyla,

$ echo 'foo' | perl -pe 's/foo/bar/g'bar

Vim'i Ex modunda kullanabilirsiniz:

ex -s -c '%s/OLD/NEW/g|x' file
  1. % tüm satırları seç

  2. s yedek oyuncu

  3. g her satırdaki tüm örnekleri değiştirme

  4. x değişiklik yapılıp yapılmadığını yazın ve çıkın

sed is the sağaç editor, bu kullanabilirsiniz | (boru) göndermek için standart akışlar (Özellikle STDIN ve STDOUT) aracılığıyla sed ve bunları programlı olarak anında değiştirerek Unix felsefe geleneğinde kullanışlı bir araç haline getirir; ancak dosyaları doğrudan kullanarak da düzenleyebilir -i parametre aşağıda belirtilmiştir.
Aşağıdakileri göz önünde bulundurun:

sed -i -e 's/few/asd/g' hello.txt

s/ için kullanılır sbulunan ifadeyi ubstitute few ile asd:

Az, cesur.


ASD, cesur.

/g "küresel" anlamına gelir, bunu tüm çizgi için yapmak anlamına gelir. Eğer bırakırsan /g (birlikte s/few/asd/, ne olursa olsun her zaman üç eğik çizgi olması gerekir) ve few aynı satırda iki kez görünür, yalnızca ilk few olarak değiştirilir asd:

Birkaç erkek, birkaç kadın, cesur.


Asd'li erkekler, az sayıda kadın, cesur olanlar.

Bu, satırların başlarındaki özel karakterleri değiştirmek gibi bazı durumlarda yararlıdır (örneğin, bazı kişilerin e-posta iş parçacıklarındaki önceki materyalleri yatay bir sekmeyle alıntılamak için kullandıkları daha büyük sembollerin yerine, daha sonra alıntılanan cebirsel eşitsizliği bırakarak) satır dokunulmamış), ancak belirttiğiniz örneğinizde bu herhangi bir yer few değiştirilmesi gerektiğinde, buna sahip olduğunuzdan emin olun /g.

Aşağıdaki iki seçenek (bayraklar) bir araya getirilir, -ie:

-i seçenek düzenlemek için kullanılır in dosyaya yerleştir hello.txt.

-e seçeneği gösterir ebu durumda çalıştırılacak xpression / komutu s/.

Not: Kullanmanız önemlidir -i -e aramak / değiştirmek için. Eğer yaparsan -ie'e' harfi eklenmiş her dosyanın yedeğini oluşturursunuz.

Yapabilir misin böyle :

locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g" 

Örnekler: tüm oluşumları [logdir', "] ([] olmadan) [logdir', os ile değiştirmek için.getcwd()] locate komutunun sonucu olan tüm dosyalarda şunları yapın::

ex1:

locate tensorboard/program.py | xargs sed -i -e "s/old_text/NewText/g"

ex2:

locate tensorboard/program.py | xargs sed -i -e "s/logdir', ''/logdir', os.getcwd()/g"

nerede [tensorboard/program.py ] aranacak dosya mı