Sed dosyasını belirli bir dize içeren bir metin dosyasındaki tüm satırları silmek için nasıl kullanabilirim?
Sed dosyasını belirli bir dize içeren bir metin dosyasındaki tüm satırları silmek için nasıl kullanabilirim?
Yanıtlar:
Çizgiyi kaldırmak ve çıktıyı standart çıkışa yazdırmak için:
sed '/pattern to match/d' ./infile
Dosyayı doğrudan değiştirmek için - BSD sed ile çalışmaz:
sed -i '/pattern to match/d' ./infile
Aynı, ancak BSD sed (Mac OS X ve FreeBSD) için - GNU sed ile çalışmaz:
sed -i '' '/pattern to match/d' ./infile
Doğrudan dosyayı değiştirmek (ve bir yedek oluşturmak) - BSD ve GNU sed ile çalışır:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfile
veya yerinde bir düzenleme yapmak istiyorsanız, -i
sed gibi bayrağı ekleyebilirsiniz sed -i '/pattern to match/d' ./infile
. Not -i
bayrağı GNU sed gerektirir ve taşınabilir değildir
sed -i.backup '/pattern to match/d' ./infile
) Bu beni yerinde düzenlemelerle karşılaştıracak.
sed
sürüm kontrollü olmayan dosyalara benzer komutlar uygulamayın .
sed -i '' '/pattern/d' ./infile
.
Ayrıca, belirli bir dizeye sahip satırları silmenin birçok yolu vardır sed
:
awk '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
grep -v "pattern" file > temp && mv temp file
Ve elbette sed
(tersi yazdırma gerçek silme işleminden daha hızlıdır):
sed -n '/pattern/!p' file
sed
örnek farklı bir davranışa sahip, sadece greps! böyle bir şey olmalı sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
Bu, dönüş değerine bağlı olarak diğer bazı örnekler için geçerli olabilir.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
gerçek 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
gerçek 0m13.671s. (Daha küçük dosyalar için fark daha büyüktür.)
Bir dosyada yer alan satırları değiştirmek için sed komutunu kullanabilirsiniz. Bununla birlikte, tersine grep'i ikinci bir dosyaya kullanmaktan ve daha sonra ikinci dosyayı orijinalin üzerine taşımaktan çok daha yavaş görünüyor.
Örneğin
sed -i '/pattern/d' filename
veya
grep -v "pattern" filename > filename2; mv filename2 filename
İlk komut yine de makinemde 3 kat daha uzun sürüyor.
sed '/pattern/d' filename > filename2; mv filename2 filename
GNU ile bunu yapmanın kolay yolu sed
:
sed --in-place '/some string here/d' yourfile
-r
seçeneği deneyin (veya -E
sürümünüze bağlı olarak). Bu regex metakarakterlerin kullanımını sağlayan +
, ?
, {...}
ve (...)
.
Kullanmayı düşünebilirsiniz ex
(standart Unix komut tabanlı bir düzenleyicidir):
ex +g/match/d -cwq file
nerede:
+
Ex komutunu ( man ex
) -c
çalıştırır wq
( çalıştır ve çık)g/match/d
- Ex komutu verilen satırları silmek için match
bkz .Yukarıdaki örnek, Unix.SE ve POSIX spesifikasyonlarındaex
bu gönderiye göre bir dosyayı yerinde düzenlemek için POSIX uyumlu bir yöntemdir .
Aradaki fark sed
şudur:
sed
Bir olan S Team, ED in- değil, bir dosya editörü. BashFAQ
Kaydedilemeyen kod, G / Ç ek yükü ve diğer bazı kötü yan etkilerin tadını çıkarmazsanız. Temel olarak bazı parametreler (yerinde / gibi -i
) standart olmayan FreeBSD uzantılarıdır ve diğer işletim sistemlerinde mevcut olmayabilir.
man ex
o bana adam verir vim
, öyle görünüyor ex
vim bir parçasıdır ... ben doğru anlama geldiğini desen sözdizimi anlamış match
olduğunu vimregex.com POSIX ve PCRE tatlar benzer ancak farklı olan?
Mac'te bununla mücadele ediyordum. Ayrıca, değişken değiştirme kullanarak yapmam gerekiyordu.
Ben de kullandım:
sed -i '' "/$pattern/d" $file
burada $file
silme işleminin gerekli olduğu dosya ve silme işlemi $pattern
için eşleştirilecek modeldir.
Ben ''
bu yorumdan aldı .
Burada dikkat edilmesi gereken şey kullanılmasıdır çift tırnak içinde "/$pattern/d"
. Tek tırnak kullandığımızda değişken çalışmaz.
sed
sonra bir parametre gerektirir -i
, bu yüzden bir yedekleme istemiyorsanız, yine de boş bir dize eklemeniz gerekir:-i ''
sed -i "/$pattern/d" $file
. Cevabınız için teşekkür ederim.
Yaklaşık 345 000 satır içeren bir dosya ile küçük bir karşılaştırma yaptım. İle yolu grep
yaklaşık 15 kat daha hızlı daha gibi görünüyor sed
bu durumda yöntemin.
Hem ve ayar LC_ALL = C olmadan denedim, önemli ölçüde zamanlamaları değiştirmek görünmüyor. Arama dizesi (CDGA_00004.pdbqt.gz.tar), dosyanın ortasında bir yerdedir.
İşte komutlar ve zamanlamalar:
time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt
real 0m0.711s
user 0m0.179s
sys 0m0.530s
time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt
real 0m0.105s
user 0m0.088s
sys 0m0.016s
time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )
real 0m0.046s
user 0m0.014s
sys 0m0.019s
Bunu da kullanabilirsiniz:
grep -v 'pattern' filename
Burada -v
sadece deseninizden başka bir şey yazdıracak (tersine eşleşme anlamına gelir).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
İlk komut dosya (ları) yerinde (-i) düzenler.
İkinci komut aynı şeyi yapar, ancak dosya adlarına .bk ekleyerek orijinal dosyaların bir kopyasını veya yedeklemesini saklar (.bk herhangi bir şeyle değiştirilebilir).
Birisinin dizelerin tam eşleşmeleri için bunu yapmak istemesi durumunda, -w
bayrağı bütün olarak grep - w'de kullanabilirsiniz . Örneğin, 11 numaralı satırları silmek, ancak 111 numaralı satırları tutmak istiyorsanız:
-bash-4.1$ head file
1
11
111
-bash-4.1$ grep -v "11" file
1
-bash-4.1$ grep -w -v "11" file
1
111
Aynı -f
anda birkaç kesin deseni hariç tutmak istiyorsanız bayrakla da çalışır . "Kara liste", her satırda "dosya" dan silmek istediğiniz çeşitli desenlere sahip bir dosyaysa:
grep -w -v -f blacklist file
-w, --word-regexp Select only those lines containing matches that form whole words.
vs-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
işlenen metni konsolda göstermek için
cat filename | sed '/text to remove/d'
işlenen metni bir dosyaya kaydetmek için
cat filename | sed '/text to remove/d' > newfile
işlenen metin bilgilerini mevcut bir dosyaya eklemek için
cat filename | sed '/text to remove/d' >> newfile
önceden işlenmiş metni işlemek için, bu durumda, kaldırılanların daha fazla satırını kaldırın
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
| more
her seferinde bir sayfanın parçalar metni gösterecektir.
Eski iyi kullanabilirsiniz ed
benzer bir şekilde düzenlemek için bir dosya cevap kullanımları olduğunu ex
. Bu durumda en büyük fark ed
, komutlarını ex
kutu gibi komut satırı argümanları olarak değil, standart girdi yoluyla almasıdır . Bir komut dosyasında kullanırken, bunu kabul etmenin genel yolu printf
komutları borulamak için kullanmaktır :
printf "%s\n" "g/pattern/d" w | ed -s filename
veya bir yorumlu metinle:
ed -s filename <<EOF
g/pattern/d
w
EOF