Bagaimana saya menggunakan sed untuk menghapus semua baris dalam file teks yang berisi string tertentu?
Bagaimana saya menggunakan sed untuk menghapus semua baris dalam file teks yang berisi string tertentu?
Jawaban:
Untuk menghapus garis dan mencetak output ke standar:
sed '/pattern to match/d' ./infile
Untuk secara langsung memodifikasi file - tidak berfungsi dengan BSD sed:
sed -i '/pattern to match/d' ./infile
Sama, tetapi untuk BSD sed (Mac OS X dan FreeBSD) - tidak bekerja dengan sed GNU:
sed -i '' '/pattern to match/d' ./infile
Untuk secara langsung memodifikasi file (dan membuat cadangan) - berfungsi dengan BSD dan GNU sed:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfile
atau jika Anda ingin melakukan in-place edit maka Anda dapat menambahkan -i
flag ke sed seperti pada sed -i '/pattern to match/d' ./infile
. Perhatikan bahwa -i
bendera memerlukan sed GNU dan tidak portabel
sed -i.backup '/pattern to match/d' ./infile
) Itu membuat saya menyeberang dengan suntingan di tempat.
sed
pada file apa pun yang tidak dikontrol versi.
sed -i '' '/pattern/d' ./infile
.
Ada banyak cara lain untuk menghapus baris dengan string spesifik selain 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
Dan tentu saja sed
(mencetak kebalikannya lebih cepat daripada penghapusan sebenarnya):
sed -n '/pattern/!p' file
sed
misalnya memiliki perilaku yang berbeda, hanya greps! harus seperti itu sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
Ini mungkin berlaku untuk beberapa contoh lain tergantung pada nilai kembali.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
0m9.294s asli. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
0m13.671s asli. (Untuk file yang lebih kecil, perbedaannya lebih besar.)
Anda dapat menggunakan sed untuk mengganti baris yang ada di file. Namun, tampaknya jauh lebih lambat daripada menggunakan grep untuk kebalikannya menjadi file kedua dan kemudian memindahkan file kedua di atas yang asli.
misalnya
sed -i '/pattern/d' filename
atau
grep -v "pattern" filename > filename2; mv filename2 filename
Perintah pertama memakan waktu 3 kali lebih lama pada mesin saya.
sed '/pattern/d' filename > filename2; mv filename2 filename
Cara mudah untuk melakukannya, dengan GNU sed
:
sed --in-place '/some string here/d' yourfile
-r
opsi (atau -E
, tergantung versi Anda). Hal ini memungkinkan penggunaan metakarakter regex +
, ?
, {...}
dan (...)
.
Anda dapat mempertimbangkan untuk menggunakan ex
(yang merupakan editor berbasis perintah Unix standar):
ex +g/match/d -cwq file
dimana:
+
mengeksekusi diberi perintah Ex ( man ex
), sama seperti -c
yang mengeksekusi wq
(menulis dan berhenti)g/match/d
- Perintah Ex untuk menghapus baris dengan yang diberikan match
, lihat: Kekuatan gContoh di atas adalah metode yang sesuai dengan POSIX untuk mengedit file di tempat sesuai pos ini di Unix.SE dan spesifikasi POSIX untukex
.
Perbedaannya sed
adalah:
sed
adalah S tream ED itor, bukan file editor. BashFAQ
Kecuali Anda menikmati kode yang tidak dapat ditonton, overhead I / O dan beberapa efek samping buruk lainnya. Jadi pada dasarnya beberapa parameter (seperti in-place / -i
) adalah ekstensi FreeBSD non-standar dan mungkin tidak tersedia pada sistem operasi lain.
man ex
memberi saya laki-laki untuk vim
, tampaknya ex
adalah bagian dari vim ... jika saya mengerti benar itu berarti sintaks pola untuk match
adalah vimregex.com yang mirip tetapi berbeda dengan rasa POSIX dan PCRE?
:g
adalah perintah yang sesuai dengan POSIX dengan beberapa perbedaan kecil . Saya menganggap PCRE didasarkan pada itu.
Saya berjuang dengan ini di Mac. Plus, saya harus melakukannya menggunakan penggantian variabel.
Jadi saya menggunakan:
sed -i '' "/$pattern/d" $file
dimana $file
file dimana penghapusan dibutuhkan dan$pattern
merupakan pola yang cocok untuk dihapus.
Saya memilih ''
dari komentar ini .
Hal yang perlu diperhatikan di sini adalah penggunaan tanda kutip ganda di "/$pattern/d"
. Variabel tidak akan berfungsi ketika kami menggunakan tanda kutip tunggal.
sed
memerlukan parameter setelahnya -i
, jadi jika Anda tidak ingin cadangan, Anda masih harus menambahkan string kosong:-i ''
sed -i "/$pattern/d" $file
. Terima kasih atas jawaban Anda.
Saya telah membuat patokan kecil dengan file yang berisi sekitar 345.000 baris. Cara dengan grep
tampaknya sekitar 15 kali lebih cepat daripada sed
metode dalam kasus ini.
Saya telah mencoba keduanya dengan dan tanpa pengaturan LC_ALL = C, sepertinya tidak mengubah timing secara signifikan. String pencarian (CDGA_00004.pdbqt.gz.tar) ada di suatu tempat di tengah file.
Berikut adalah perintah dan timingnya:
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
Anda juga dapat menggunakan ini:
grep -v 'pattern' filename
Di sini -v
hanya akan mencetak selain pola Anda (itu berarti kecocokan terbalik).
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Perintah pertama mengedit file di tempat (-i).
Perintah kedua melakukan hal yang sama tetapi menyimpan salinan atau cadangan file asli dengan menambahkan .bk ke nama file (.bk dapat diubah menjadi apa saja).
Untuk berjaga - jaga seandainya seseorang ingin melakukannya untuk kecocokan string yang tepat, Anda dapat menggunakan -w
flag dalam grep - w secara keseluruhan. Misalnya, jika Anda ingin menghapus garis yang memiliki angka 11, tetapi pertahankan garis dengan angka 111:
-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
Ini juga berfungsi dengan -f
bendera jika Anda ingin mengecualikan beberapa pola yang tepat sekaligus. Jika "daftar hitam" adalah file dengan beberapa pola pada setiap baris yang ingin Anda hapus dari "file":
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
untuk menampilkan teks yang dirawat di konsol
cat filename | sed '/text to remove/d'
untuk menyimpan teks yang dirawat ke dalam file
cat filename | sed '/text to remove/d' > newfile
untuk menambahkan info teks yang diperlakukan file yang ada
cat filename | sed '/text to remove/d' >> newfile
untuk memperlakukan teks yang sudah diperlakukan, dalam hal ini hapus lebih banyak baris dari apa yang telah dihapus
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
yang | more
akan menampilkan teks dalam potongan satu halaman pada satu waktu.
Anda bisa menggunakan yang lama ed
untuk mengedit file dengan cara yang mirip dengan jawaban yang digunakan ex
. Perbedaan besar dalam hal ini adalah bahwa ed
mengambil perintah melalui input standar, bukan sebagai argumen baris perintah seperti ex
bisa. Saat menggunakannya dalam skrip, cara biasa untuk mengakomodasi ini adalah dengan menggunakan printf
perintah pipa ke sana:
printf "%s\n" "g/pattern/d" w | ed -s filename
atau dengan heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF