Yanıtlar:
sed -i 's/original/new/g' file.txt
Açıklama:
sed
= Akış Düzenleyici-i
= yerinde (yani orijinal dosyaya geri kaydet)Komut dizesi:
s
= substitute komutuoriginal
= değiştirilecek kelimeyi tanımlayan normal bir ifade (veya sadece kelimenin kendisi)new
= ile değiştirilecek meting
= global (yani hepsini değiştir ve yalnızca ilk oluşumu değil)file.txt
= dosya adı
sed
eşleşir. -r
Bunun yerine genişletilmiş RE'ler kullanmak istiyorsanız bir bayrak ekleyin .
/
eşleştirmeniz gereken karakterse, ayırıcı olarak başka bir karakter kullanabilirsiniz (örn. 's_old/text_new/text_g'
). Aksi takdirde, kelimenin tam anlamıyla bir karakter elde etmek için \
herhangi birinden önce koyabilirsiniz $ * . [ \ ^
.
sed -i '.bak' 's/original/new/g' file.txt
ayrıca sıfır uzunluklu bir uzantıyla çalıştırılabilir sed -i '' 's/original/new/g' file.txt
, bu da yedekleme yapmaz.
Bunu yapmanın birkaç farklı yolu vardır. Biri sed
ve Regex kullanıyor . SED, metni filtrelemek ve dönüştürmek için bir Akış Düzenleyicisidir. Bir örnek aşağıdaki gibidir:
marco@imacs-suck: ~$ echo "The slow brown unicorn jumped over the hyper sleeping dog" > orly
marco@imacs-suck: ~$ sed s/slow/quick/ < orly > yarly
marco@imacs-suck: ~$ cat yarly
The quick brown unicorn jumped over the hyper sleeping dog
Daha mantıklı olabilir başka bir yolu da < strin
ve > strout
borularla olduğunu!
marco@imacs-suck: ~$ cat yarly | sed s/unicorn/fox/ | sed s/hyper/lazy/ > nowai
marco@imacs-suck: ~$ cat nowai
The quick brown fox jumped over the lazy sleeping dog
cat
içinde cat file | sed '...'
gereksizdir. Doğrudan söyleyebilirsiniz sed '...' file
.
sed -i'.bak' -e 's/unicorn/fox/g;s/hyper/brown/g' yarly
eğe dosyası alacak ve bir yedekleme yaparken yerinde 2 değişiklik yapacaktır. time bash -c "$COMMAND"
Zamanın kullanılması , bu sürümün ~ 5 kat daha hızlı olduğunu gösteriyor.
Bunu başarmanın çok yolu var. Dize değiştirme ile neyin başarmaya çalıştığının karmaşıklığına bağlı olarak ve kullanıcının tanıdığı araçlara bağlı olarak, bazı yöntemler diğerlerinden daha fazla tercih edilebilir.
Bu cevapta input.txt
burada verilen tüm örnekleri test etmek için kullanabileceğiniz basit bir dosya kullanıyorum . Dosya içeriği:
roses are red , violets are blue
This is an input.txt and this doesn't rhyme
Bash aslında metin işleme amaçlı değildir, ancak parametre genişletme yoluyla basit değişimler yapılabilir , özellikle burada basit yapıyı kullanabiliriz ${parameter/old_string/new_string}
.
#!/bin/bash
while IFS= read -r line
do
case "$line" in
*blue*) printf "%s\n" "${line/blue/azure}" ;;
*) printf "%s\n" "$line" ;;
esac
done < input.txt
Bu küçük komut dosyası yerinde değiştirme işlemi yapmaz; bu, yeni metni yeni dosyaya kaydetmeniz ve eski dosyadan kurtulmanız gerektiği anlamına gelir; mv new.txt old.txt
Yan not: neden while IFS= read -r ; do ... done < input.txt
kullanıldığını merak ediyorsanız , bu temel olarak kabuğun satır satır dosya okuma biçimidir. Bkz bu başvuru için.
Bir metin işleme aracı olan AWK, bu görev için oldukça uygundur. Düzenli ifadelere dayalı basit değiştirmeler ve çok daha gelişmiş olanları yapabilir . İki işlev sunar: sub()
ve gsub()
. Birincisi, sadece ilk oluşumun yerini alır, ikincisi ise tüm dizedeki oluşumları değiştirir. Örneğin, eğer dizgemiz varsa one potato two potato
, sonuç şu 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 yapmak input.txt
kolay olacaktır:
awk '{sub(/blue/,"azure")}1' input.txt
Sahip olduğunuz AWK sürümüne bağlı olarak, yerinde düzenleme olabilir veya olmayabilir, bu nedenle olağan uygulama yeni metni kaydeder ve değiştirir. Örneğin böyle bir şey:
awk '{sub(/blue/,"azure")}1' input.txt > temp.txt && mv temp.txt input.txt
Sed bir çizgi editörüdür. Ayrıca düzenli ifadeler kullanır, ancak basit değişiklikler için yapmanız yeterlidir:
sed 's/blue/azure/' input.txt
Bu araç için iyi olan şey, -i
bayrakla etkinleştirebileceğiniz yerinde düzenlemeye sahip olmasıdır .
Perl, genellikle metin işlemede 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 değiştirme işlemi şu şekilde yapılabilir:
perl -pe 's/blue/azure/' input.txt
Sed gibi perl de -i bayrağına sahiptir.
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 replace()
, ki bunlar arasında , eğer böyle bir değişkeniniz varsa var="Hello World"
,var.replace("Hello","Good Morning")
Dosyayı okumak ve içindeki dizeyi değiştirmek için basit bir yol böyle olurdu:
python -c "import sys;lines=sys.stdin.read();print lines.replace('blue','azure')" < input.txt
Ancak Python ile, ayrıca betiğin içinden de yapabileceğiniz yeni bir dosyaya çıkmanız gerekir. Örneğin, işte basit bir tane:
#!/usr/bin/env python
import sys
import os
import tempfile
tmp=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ı input.txt
komut satırı argümanı olarak çağrılmalıdır . Python betiğini komut satırı argümanıyla çalıştırmanın tam komutu şöyle olacaktır:
$ ./myscript.py input.txt
veya
$ python ./myscript.py input.txt
Tabii ki, ./myscript.py
geçerli çalışma dizininizde olduğundan ve ilk olarak çalıştırılabilir olarak ayarlandığından emin olun.chmod +x ./myscript.py
Python ayrıca düzenli ifadelere sahip olabilir, özellikle, daha gelişmiş değişimler için kullanılabilecek fonksiyona re
sahip bir modül var re.sub()
.
tr
komutu unix olarak kullanmaktır
tr
başka harika bir araç, ancak örneğin (karakter setleri değiştirilmesi için olduğuna dikkat tr abc cde
çevirmek olacaktır a
için c
, b
hiç d
bu gibi tam kelimeleri değiştirerek biraz farklıdır. sed
Yapython
Vim'i Ex modunda kullanabilirsiniz:
ex -s -c '%s/OLD/NEW/g|x' file
%
tüm satırları seç
s
vekil
g
her satırdaki tüm örnekleri değiştirin
x
Değişiklik yapılmışsa yaz (varsa)
Awk’nin gsub komutuyla
awk '{gsub(/pattern/,"replacement")}' file
Örnek:
awk '{gsub(/1/,"0");}' file
Yukarıdaki örnekte, tüm 1'ler, bulunduğu sütuna bakılmaksızın 0 ile değiştirilir.
Belirli bir sütunda değişiklik yapmak istiyorsanız, böyle yapın,
awk '{gsub(/pattern/,"replacement",column_number)}' file
Örnek:
awk '{gsub(/1/,"0",$1);}' file
Yalnızca ilk sütunda 1 ile 0 olur.
Perl’den
$ echo 'foo' | perl -pe 's/foo/bar/g'
bar
inotifywait
altında izliyorum sh
ve verileri CSV biçiminde rapor ediyorum (çünkü özel biçim buggy). Sonra CSV belgesini kabuk betiklerinde kullanmanın basit bir yolu olmadığını düşündüm ... Ve çok hafif istiyorum. Bu yüzden CSV'yi ayrıştırmak ve raporlamak için oldukça basit bir senaryo başlattım. CSV spesifikasyonunu okudum ve beklediğimden daha ayrıntılı olduğunu ve çift tırnak içine alınmış çoklu satır değerini desteklediğini fark ettim. sed
Tokenleştirmeye güveniyordum ama kısa sürede sed
multiline dediğimiz şeyin iki hatta kadar olduğunu fark ettim . Peki ya CSV değerlerinden biri ikiden fazla satıra yayılıyorsa?
sed
olduğunu s Team, ed in- kullanabileceğiniz ki |
göndermeye (boru) standart akışları aracılığıyla (Standart giriş ve çıkışı özellikle) sed
ve Unix felsefesi geleneğinde bir araçtır yapım anında programlı bunları değiştirmek; ancak, -i
aşağıda belirtilen parametreyi kullanarak da dosyaları doğrudan düzenleyebilir .
Aşağıdakileri göz önünde bulundurun :
sed -i -e 's/few/asd/g' hello.txt
s/
için kullanılır s Bulunan ifade yerini tutmaz few
ile asd
:
Birkaç, cesur.
Asd, cesur.
/g
"Global" anlamına gelir, bunu bütün çizgi için yapmak anlamına gelir. Bırakırsanız /g
(ile s/few/asd/
ne olursa olsun her zaman üç eğik çizgi olması gerekir) ve few
aynı satırda iki kez görünürse, yalnızca ilki few
olarak değiştirilir asd
:
Birkaç erkek, birkaç kadın, cesur.
Asd adamları, az sayıda kadın, cesur.
Bu, bazı durumlarda, satırların başlangıcında özel karakterlerin değiştirilmesi gibi (örneğin, bazı kişilerin e-posta dizilerinde önceki materyali alıntı yapmak için kullandıklarından daha büyük sembollerin yerine, satırın ilerisinde alıntı yapılan bir cebirsel eşitsizlik bırakarak, yatay bir sekmeyle değiştirmek gibi) yararlıdır. dokunulmamış), ancak örneğinizde herhangi bir yerde few
meydana geldiğini belirttiğiniz yerde değiştirilmeli, bunun olduğundan emin olun /g
.
Aşağıdaki iki seçenek (bayraklar) bire birleştirilmiştir -ie
:
-i
seçenek düzenlemek için kullanılır ı n dosyada yer hello.txt
.
-e
seçenek bu durumda, çalışacak e xpression / komutunu gösterir s/
.
Not: -i -e
Aramak / değiştirmek için kullanmanız önemlidir . Bunu yaparsanız -ie
, 'e' harfi eklenmiş her dosyanın bir yedeğini yaratırsınız.
Böyle yapabilirsin:
locate <part of filaname to locate> | xargs sed -i -e "s/<Old text>/<new text>/g"
Örnekler: [logdir ',' '] ([] olmadan) tüm oluşumları, locate komutunun sonucu olan tüm dosyalarda [logdir', os.getcwd ()] ile değiştirmek için, ş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"
[tensorboard / program.py] aranacak dosyada
logdir', ''
-> /logdir', os.getcwd()
) bu cevabı ayrıştırmayı zorlaştırır. Ayrıca, cevabınızın öncelikle sed'in kullanılacağı dosyaları bulacağını belirtmeye değer, çünkü bu sorunun bir parçası değil.