Bagaimana saya akan menggunakan sed untuk menghapus semua baris dalam sebuah file teks yang berisi string tertentu?
Untuk menghapus baris dan mencetak output ke standar out:
sed '/pattern to match/d' ./infile
Untuk langsung mengubah file – tidak bekerja dengan BSD sed:
sed -i '/pattern to match/d' ./infile
Yang sama, tapi untuk BSD sed (Mac OS X dan FreeBSD) – tidak bekerja dengan GNU sed:
sed -i '' '/pattern to match/d' ./infile
Untuk langsung mengubah file (dan membuat cadangan) – bekerja dengan BSD dan GNU sed:
sed -i.bak '/pattern to match/d' ./infile
Ada banyak cara lain untuk menghapus baris dengan string tertentu 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
(cetak invers lebih cepat dari yang sebenarnya penghapusan):
sed -n '/pattern/!p' file
Anda dapat menggunakan sed untuk menggantikan garis-garis di tempat dalam sebuah file. Namun, hal itu tampaknya jauh lebih lambat daripada menggunakan grep untuk inverse ke file kedua dan kemudian menggerakkan kedua file di atas.
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 pula.
Anda dapat mempertimbangkan untuk menggunakan ex
(yang merupakan standar Unix berbasis perintah editor):
ex +g/match/d -cwq file
dimana:
+
mengeksekusi diberikan Ex perintah (man ex
), sama seperti -c
yang mengeksekusi wq
(menulis dan berhenti)g/pertandingan/d
- Ex perintah untuk menghapus baris dengan diberikan pertandingan
, lihat: Kekuatan dari gContoh di atas adalah POSIX-compliant metode untuk di-tempat mengedit file seperti ini posting di Unix.SE dan POSIX spesifikasi untuk ex
.
Perbedaan dengan sed
adalah bahwa:
sed
adalah Stream EDitor, bukan file editor.BashFAQ
Kecuali anda menikmati unportable kode, I/O overhead dan beberapa lainnya efek samping yang buruk. Jadi pada dasarnya beberapa parameter (seperti di-tempat/-i
) adalah non-standar FreeBSD ekstensi dan mungkin tidak tersedia pada sistem operasi lain.
Saya berjuang dengan ini di Mac. Plus, aku harus melakukannya dengan menggunakan variabel pengganti.
Jadi saya digunakan:
sed -i '', "/$pola/d" $file
di mana $file
adalah penghapusan file yang mana yang dibutuhkan dan $pola
adalah pola akan dicocokkan untuk penghapusan.
Saya mengambil''
dari ini komentar.
Hal yang perlu diperhatikan di sini adalah penggunaan tanda kutip ganda di "/$pola/d"
. Variabel won't bekerja ketika kita menggunakan tanda kutip tunggal.
Aku telah acuan dengan file yang berisi sekitar 345 000-garis. Cara dengan grep
tampaknya menjadi sekitar 15 kali lebih cepat dari sed
metode dalam kasus ini.
Aku telah berusaha baik dengan dan tanpa pengaturan LC_ALL=C, tampaknya tidak mengubah timing secara signifikan. Pencarian string (CDGA_00004.pdbqt.gz.tar) adalah suatu tempat di tengah-tengah file.
Berikut ini adalah perintah-perintah dan timing:
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
SED:
AWK:
GREP:
perl -i -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3
Perintah pertama mengedit file(s) inplace (-i).
Perintah kedua melakukan hal yang sama, tapi membuat salinan atau backup dari file asli(s) dengan menambahkan .bk ke nama berkas (.bk bisa berubah menjadi apa-apa).
Hanya dalam kasus seseorang ingin melakukan itu untuk pertandingan yang tepat dari string, anda dapat menggunakan w
bendera di grep - w untuk seluruh. Artinya, sebagai contoh jika anda ingin menghapus baris yang memiliki nomor 11, tapi tetap lines dengan nomor 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
Ia juga bekerja dengan -f
bendera jika anda ingin mengecualikan beberapa pola yang tepat sekaligus. Jika "blacklist" adalah file dengan beberapa pola pada masing-masing baris yang ingin anda hapus dari "berkas":
grep -w -v -f blacklist file