Saya ingin menghapus baris dari file yang hanya berisi karakter tertentu, jika ada lebih dari satu kali atau tidak ada maka simpan baris dalam file.
Sebagai contoh:
DTHGTY
FGTHDC
HYTRHD
HTCCYD
JUTDYC
Di sini, karakter yang ingin saya hapus C
begitu, perintahnya harus menghapus garis FGTHDC
dan JUTDYC
karena mereka memiliki C
tepat sekali.
Bagaimana saya bisa melakukan ini menggunakan salah satu sed
atau awk
?
sumber
awk
pemisah bidang yang cerdik!awk 'BEGIN { print "FS={" FS"}","OFS={" OFS "}";} {printf "%d fields : ",NF; for (i=1;i<=NF;i++) {printf "{" $i "} ";}; print "" }'
dan memberinya makan beberapa baris, beberapa memiliki banyak spces, dan yang lainnya mulai dengan spasi)pendekatan sed :
-i
Opsi memungkinkan modifikasi file di tempat/^[^C]*C[^C]*$/
- cocok dengan garis yangC
hanya mengandung sekalid
- hapus baris yang cocoksumber
Ini dapat dilakukan dengan
sed
:Kode:
Hasil:
Bagaimana?
C
via/C.*C/p
C
via/C/d
, ini termasuk baris yang sudah dicetak pada langkah 1sumber
Ini menghilangkan garis dengan tepat satu kemunculan C.
Ekspresi reguler
[^C]
cocok dengan satu karakter yang bukan C (atau baris baru), dan operator pengulangan (alias bintang Kleene)*
menentukan nol atau lebih pengulangan dari ekspresi sebelumnya.Output default dari
grep
(dan sebagian besar alat berorientasi teks lainnya) adalah output standar; redirect ke file baru dan mungkin memindahkannya di atas file asli jika itu yang Anda inginkan. Regex yang sama dapat digunakan dengansed -i
untuk mengedit di tempat:(Pada beberapa platform, terutama * BSD termasuk macOS,
-i
opsi membutuhkan argumen, seperti-i ''
.)sumber
sed -i '/^[^C]*C[^C]*$/d' file
- Kedengarannya seperti itu diposting sebelumnya, bagaimana menurut Anda, plagiarisme?grep
jawabannya tetapi jelas dengan mudah meluas kesed -i
varian. Tidak melihat jawaban Anda karena saya mencarigrep
jawaban sebelumnya .-i
dengansed
dan alih-alih mengarahkan ke file baru dan mengganti yang asli dengan itu jikased
utilitas keluar tanpa kesalahan.grep -vx '[^C]*C[^C]*'
grep
karena lebih jelas dan lebih kuat (khususnya,sed
memiliki kode keluar kurang informatif).Alat POSIX untuk mengedit skrip file (daripada mencetak konten yang dimodifikasi ke standar keluar) adalah
ex
.Tentu saja Anda dapat menggunakan
sed -i
jika versi Sed Anda mendukungnya, perlu diketahui bahwa itu tidak portabel jika Anda sedang menulis skrip yang dimaksudkan untuk dijalankan pada berbagai jenis sistem.David Foerster bertanya dalam komentar:
Jawab: Ya.
Untuk
printf
vs.echo
itu adalah masalah portabilitas; lihat Mengapa printf lebih baik daripada gema? Dan juga lebih mudah untuk memotong garis baru antara perintah yang digunakanprintf
.Untuk
printf ... | ex
vs.ex -c ...
, ini masalah penanganan kesalahan. Untuk perintah khusus ini tidak masalah, tetapi secara umum itu penting; misalnya, coba pakaidalam naskah. Kontras dengan yang berikut ini:
Yang pertama akan hang dan menunggu input; yang kedua akan keluar ketika EOF diterima oleh
ex
perintah, sehingga skrip akan berlanjut. Ada beberapa solusi alternatif, sepertis///e
, tetapi tidak ditentukan oleh POSIX. Saya lebih suka menggunakan formulir portabel, yang ditunjukkan di atas.Untuk
g
perintah, harus ada baris baru di akhir, dan saya lebih suka menggunakanprintf
untuk membungkus perintah daripada menyematkan baris baru dalam tanda kutip tunggal.sumber
printf
dan bukanecho
atau sesuatu seperti ituex -c COMMAND
?printf
vs.echo
(meskipun saya biasanya lebih sukaecho
ketika argumen tersebut dikodekan) tetapi saya belum menggunakannyaex
secara luas sejauh ini.Berikut adalah beberapa opsi menggunakan perl.
Karena Anda hanya mencocokkan satu karakter, Anda dapat menggunakan
tr/C//
(terjemahan, tanpa penggantian), untuk mengembalikan jumlah kecocokan dariC
:Secara umum, jika Anda ingin mencocokkan string multi-karakter atau ekspresi reguler, maka Anda dapat menggunakan ini:
Ini menetapkan kecocokan dari ekspresi reguler
/C/g
ke daftar@m
dan mencetak garis ketika panjang daftar itu tidak1
.The
-i
switch dapat ditambahkan ke edit "di tempat".sumber
sumber
sed
,t #...
biasanya bercabang ke label yang disebut#...
di sebagian besarsed
implementasi lainnya .!b
GNU sed karena cabang tidak suka apa pun kecuali label atau baris baru setelah itu.b
,t
,:
,}
(danr file
,w file
...) tidak dapat memiliki perintah setelah mereka pada baris yang sama. Anda juga dapat menggunakan-e
opsi terpisah .g
pengubah.Bagi siapa pun yang ingin
awk
secara khusus, saya akan menawarkanlewati garis jika cocok dengan pola, cetak sebaliknya. Anda tidak benar-benar perlu
{print}
, Anda dapat menggunakan//
dan mencetak standar, tapi saya pikir itu lebih jelas dijabarkan.Pikiran pertama saya adalah menggunakan
egrep -v
dengan pola yang sama, tetapi itu tidak benar-benar menjawab pertanyaan yang diajukan.sumber
{next}
? Katakan sajaawk '/pattern/ {next} 1'
dan semua garis yang tidak cocok dengan pola akan dicetak. Atau, lebih baik,awk '!/pattern/'
untuk langsung mencetaknya.!/pattern/
(yang entah bagaimana menyelinap di pikiranku) tapi aku lebih suka melihat penjelasan sendiri//{print}
daripada samar1
. Asumsikan kompetensi dan kelancaran paling sedikit dari orang berikutnya untuk menjaga kode Anda, konsisten dengan tidak menjadikannya kurang efisien atau efektif.