Hapus garis yang tidak dimulai dengan pola dari set pola yang diberikan


10

Saya memiliki file yang berisi data seperti ini:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Pertanyaan: Saya ingin menghapus baris apa pun yang tidak dimulai dengan string berikut:

report  
-th  
-to

itu berarti output keinginan akan menghapus semua titik dan hash tengah yang tidak diinginkan dan akan terlihat seperti ini:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ etc solusi apa pun yang akan bekerja.

Jawaban:


15

Menggunakan seduntuk memodifikasi file di tempat:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Ini menginstruksikan seduntuk menghapus semua baris yang tidak cocok dengan pola. Pola itu sendiri adalah ^(mulai dari garis), diikuti oleh salah satu reportatau -tdiikuti oleh hatau o.

Anda harus mencatat bahwa ini bukan modifikasi aktual di tempat: sedmembuat salinan cadangan sementara dan menimpa file asli dengannya.

Jika Anda ingin sedmenyimpan salinan cadangan dari file asli (yang mungkin merupakan ide bagus jika file tersebut berisi data penting), berikan -isaklar ekstensi untuk membuat file cadangan:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

akan memodifikasi your_filedan membuat cadangan dari yang disebut asli your_file.bak.

Catatan tambahan

Tolong jangan salah mengartikan niat saya atau menyinggung ini, tapi saya perhatikan bahwa Anda memiliki banyak pertanyaan terkait pemrosesan teks / regex yang serupa. Saya menyarankan Anda untuk mulai belajar sed, awkdan grepAnda sendiri untuk membantu mempercepat produktivitas Anda. Sekali lagi, jangan salah paham, saya terlalu senang untuk membantu (seperti kebanyakan orang di sekitar sini); hanya saja saya pikir Anda dapat mengambil manfaat besar dari mengambil alat ini untuk penggunaan sehari-hari Anda.

Hanya untuk membuktikan betapa bermanfaatnya orang-orang di sekitar sini, pertimbangkan saran @ slm dalam komentar di bawah ini dan jangan ragu untuk mampir ke ruang obrolan ini kapan saja untuk pertanyaan.


1
Ekspresi reguler Anda sepertinya tidak perlu samar. Saya pikir Anda benar-benar menggunakan lebih banyak karakter daripada jika Anda baru saja mencantumkan tiga opsi secara eksplisit.
nispio

1
@nispio saya tahu, tetapi kemungkinan akan lebih efisien jika file yang dimaksud besar.
Joseph R.

Menarik. Saya selalu mengukur regexps dalam hal panjang atau keterbacaan. Saya tidak pernah terlalu memikirkan kecepatan eksekusi. Saya rasa saya tidak cukup tahu tentang bagaimana mereka dievaluasi untuk menilai apa yang cepat, tetapi saya berasumsi bahwa itu juga implementasi spesifik, kan?
nispio

3
Mengulang kembali apa yang dikatakan Joseph tentang bersedia membantu, jika Anda memiliki pertanyaan umum yang tidak sesuai dengan gaya Tanya Jawab, Anda selalu dapat mencoba mengobrol dengan kami di ruang obrolan untuk situs ini. chat.stackexchange.com/rooms/26/unix-and-linux . Beberapa dari kita tinggal di sana 8-)
slm

@slm Terima kasih untuk ini. Saya akan menambahkannya ke jawaban saya.
Joseph R.

10

Anda dapat menggunakan grep sederhana untuk ini:

$ grep -e '^report\|^-th\|^-to' filename

1
Ini bukan penghematan, tetapi Anda bisa menggabungkan -th/ -tomenjadi -t[ho].
Kevin

grep -eatauegrep
Olivier Dulac

2

Menggunakan sed:

sed -n -e '/^report\|^-th\|^-to/p' filename

Ini bukan penghematan, tetapi Anda bisa menggabungkan -th/ -tomenjadi -t[ho].
Kevin

1
@ Kevin Itu benar. Lihat percakapan saya dengan Joseph R. di komentar untuk jawabannya.
nispio

2

Menggunakan awk:

awk '/^report|^-t[ho]/' file

Ini bukan penghematan, tetapi Anda bisa menggabungkan -th/ -tomenjadi -t[ho].
Kevin

1

Penanya telah membuat dua poin:

  • ingin menghapus baris apa pun yang tidak dimulai dengan "laporkan" atau "-th" atau "-to".
  • output yang diinginkan harus menghilangkan "semua titik dan hash tengah yang tidak diinginkan"

Solusinya, saat ini, membahas poin pertama dan dengan demikian juga yang kedua. Tapi misalkan file lebih besar dan terlihat seperti:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

Tidak akan membahas poin kedua OP lakukan yg diperlukan?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

melakukan pekerjaan menghilangkan garis yang mungkin tidak diinginkan yang hanya berisi spasi, titik dan garis putus-putus dan mempertahankan sisanya, apa pun itu.
Saya akan berpikir bahwa risiko dari kedua pendekatan tersebut adalah sifat dari file tersebut tidak didefinisikan dengan benar.


0

Menggunakan Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

atau, untuk mengedit di tempat (seperti sed, perljuga akan membuat cadangan sementara jadi ini tidak benar di tempat mengedit):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Itu akan membuat salinan dari file asli yang dipanggil filename.bakdan menimpa file asli Anda dengan versi yang diedit.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.