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
%
tüm satırları seçs
yedek oyuncug
her satırdaki tüm örnekleri değiştirmex
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ı