Bir metin dosyasından, belirli bir dize içeren tüm satırları nasıl silebilirim?


Yanıtlar:


2759

Ç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

13
Teşekkürler, ancak dosyadan silmek gibi görünmüyor, ancak metin dosyası içeriğini bu dize olmadan yazdırın.
Bir Clockwork Orange

115
@A Clockwork: evet, çıktıyı yeni bir dosyaya benzer bir şeyle yönlendirmeniz gerekir sed '/pattern to match/d' ./infile > ./newfileveya yerinde bir düzenleme yapmak istiyorsanız, -ised gibi bayrağı ekleyebilirsiniz sed -i '/pattern to match/d' ./infile. Not -ibayrağı GNU sed gerektirir ve taşınabilir değildir
SiegeX

16
Sed bazı lezzet için; sed'in "-i" bayrağı bir uzantının sağlanmasını gerektiriyordu. (örneğin sed -i.backup '/pattern to match/d' ./infile) Bu beni yerinde düzenlemelerle karşılaştıracak.
avelis

9
@SiegeX Daha da iyisi, sedsürüm kontrollü olmayan dosyalara benzer komutlar uygulamayın .
MatrixFrog

84
Mac OS X kullanıcıları için bir not daha: bazı nedenlerden dolayı, -i bayrağının, yalnızca boş bir dize olsa bile, bir argümanın iletilmesini gerektirir sed -i '' '/pattern/d' ./infile.
geerlingguy

631

Ayrıca, belirli bir dizeye sahip satırları silmenin birçok yolu vardır sed:

AWK

awk '!/pattern/' file > temp && mv temp file

Yakut (1.9+)

ruby -i.bak -ne 'print if not /test/' file

Perl

perl -ni.bak -e "print unless /pattern/" file

Kabuk (bash 3.2 ve üstü)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

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

4
bir desenle belirli bir satırı ve hemen üstündeki satırı nasıl silebilirim? Farklı veriler arasındaki binlerce satırda para cezası var.
oortcloud_domicile

1
OS / X'te kabuk varyasyonu önde gelen alanları korumaz, ancak grep -v varyasyonu benim için iyi çalıştı.
Paul Beusterien

13
sedörnek farklı bir davranışa sahip, sadece greps! böyle bir şey olmalı sed -n -i '/pattern/!p' file.
caesarsol

8
Her satır desenle eşleştiğinde grep sürümü çalışmaz. Daha iyi yapın: grep -v "pattern" file > temp; mv temp fileBu, dönüş değerine bağlı olarak diğer bazı örnekler için geçerli olabilir.
Chris Maes

1
"tersi yazdırma gerçek silme işleminden daha hızlıdır" - Makinemde değil (2012 MacBook Air, OS X 10.13.2). Dosyası oluşturun: seq -f %f 10000000 >foo.txt. sed d: time sed -i '' '/6543210/d' foo.txtgerçek 0m9.294s. sed! p: time sed -i '' -n '/6543210/!p' foo.txtgerçek 0m13.671s. (Daha küçük dosyalar için fark daha büyüktür.)
jcsahnwaldt diyor GoFundMonica

252

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.


19
Sadece bir performans karşılaştırması denediğiniz için cevabınızı oylayın!
anuragw

4
Mevcut dosyanın üzerine grep satırı ile yazma seçeneği sunan +1.
Rhyuk

2
İkinci 'grep' çözümü de büyük dosyalar için daha iyi
14'te

3
Performans farkının bu olsaydı ne olacağını merak ediyorumsed '/pattern/d' filename > filename2; mv filename2 filename
Pete

8
(ubuntu / usr / share / dict / words kullanarak) grep ve mv: 0.010s | yerde sed: 0.197s | sed ve mv: 0.031s
ReactiveRaven

77

GNU ile bunu yapmanın kolay yolu sed:

sed --in-place '/some string here/d' yourfile

56
Bu soru-cevap dizisine rastlayan ve kabuk komut dosyalarına yeni başlayanlar için kullanışlı bir ipucu: Kısa seçenekler komut satırında bir kerelik kullanımlar için uygundur, ancak daha okunabilir olduklarından komut dosyalarında uzun seçenekler tercih edilmelidir.
Dennis

3
-İn-place bayrağı için +1. Bunu izin korumalı dosyalar üzerinde test etmek gerekiyor. (bazı kullanıcı ovma yapmak zorunda.)
Bee Kay

8
Uzun seçeneğin yalnızca GNU sed. Mac ve BSD kullanıcılarının bunu yapmak için gsed yüklemeleri gerekecek.
Matt

Başka bir ipucu: normal ifadeniz eşleşmiyor gibi görünüyorsa, -rseçeneği deneyin (veya -Esürümünüze bağlı olarak). Bu regex metakarakterlerin kullanımını sağlayan +, ?, {...}ve (...).
rjh

Diskinizde daha fazla yer olmadığında ve metni başka bir dosyaya kopyalayamadığınızda doğru yanıt budur. Bu komut ne sorgulandı?
ferreirabraga

38

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 matchbkz .

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:

sedBir 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.


5
Bu harika ... Ben ne zaman man exo bana adam verir vim, öyle görünüyor exvim bir parçasıdır ... ben doğru anlama geldiğini desen sözdizimi anlamış matcholduğunu vimregex.com POSIX ve PCRE tatlar benzer ancak farklı olan?
Anentropik

1
:g olan POSIX uyumlu bazılarıyla komut küçük farkla . PCRE'nin buna dayandığını varsayıyorum.
kenorb

16

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 $filesilme işleminin gerekli olduğu dosya ve silme işlemi $patterniç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.


3
Mac sedsonra bir parametre gerektirir -i, bu yüzden bir yedekleme istemiyorsanız, yine de boş bir dize eklemeniz gerekir:-i ''
wisbucky

Kabuk kullanımı için sed -i "/$pattern/d" $file. Cevabınız için teşekkür ederim.
ashwaqar

14

Yaklaşık 345 000 satır içeren bir dosya ile küçük bir karşılaştırma yaptım. İle yolu grepyaklaşık 15 kat daha hızlı daha gibi görünüyor sedbu 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

Hangi platformdasın? Hangi sed / perl / grep sürümlerini kullanıyorsunuz?
hagello

Kullandığım platform Linux (Gentoo). Sed sürümü GNU sed v 4.2.2, perl sürümü perl 5 (test sırasında hangi revizyonu kullandığımı söyleyemiyorum) ve grep (GNU) sürüm 3.0.
Jadzia

14

Bunu da kullanabilirsiniz:

 grep -v 'pattern' filename

Burada -vsadece deseninizden başka bir şey yazdıracak (tersine eşleşme anlamına gelir).


Belirli bir dize içeren bir dizindeki satırları nasıl silebilirim
namannimmo

13

grepSizinle benzer bir sonuç almak için bunu yapabilirsiniz:

echo "$(grep -v "pattern" filename)" >filename

4
Bu sadece bashkabuk veya benzeri için iyidir (değil tcsh).
esmit


4
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).


2

echo -e "/thing_to_delete\ndd\033:x\n" | vim file_to_edit.txt


2

Birisinin dizelerin tam eşleşmeleri için bunu yapmak istemesi durumunda, -wbayrağı 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ı -fanda 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

Biraz yanıltıcı. -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 $.
Sai


0

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

| moreher seferinde bir sayfanın parçalar metni gösterecektir.


0

Eski iyi kullanabilirsiniz edbenzer bir şekilde düzenlemek için bir dosya cevap kullanımları olduğunu ex. Bu durumda en büyük fark ed, komutlarını exkutu 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 printfkomutları 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
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.