Saya memiliki banyak file dan saya ingin menemukan yang berisi garis berurutan yang dimulai dengan string tertentu.
Misalnya untuk file berikut:
Aaaaaaaaaaaa
Baaaaaaaaaaa
Cxxxxxxxxx
Cyyyyyyyyy
Czzzzzzzzz
Abbbbbbbbbbb
Bbbbbbbbbbbb
Caaaaaa
Accccccccccc
Bccccccccccc
Cdddddd
Ceeeeee
Ada lebih dari satu baris yang dimulai dengan 'C', jadi saya ingin file ini ditemukan dengan perintah.
Misalnya untuk file berikut:
Aaaaaaaaaaaa
Baaaaaaaaaaa
Cxxxxxxxxx
Abbbbbbbbbbb
Bbbbbbbbbbbb
Caaaaaa
Accccccccccc
Bccccccccccc
Cdddddd
Selalu ada satu baris yang dimulai dengan 'C', saya tidak ingin file ini. Saya berpikir untuk menggunakan a grep
atau a sed
tetapi saya tidak tahu persis bagaimana melakukannya. Mungkin menggunakan regexp ^C.*$^C
atau sesuatu seperti itu. Ada ide ?
C
contoh kedua Anda.C
?grep
versi yang lebih lama .Jawaban:
Dengan
pcregrep
:POSIXly:
(meskipun itu berarti membaca semua file sepenuhnya dengan
awk
implementasi yang tidak mendukungnextfile
).Dengan versi GNU
grep
hingga 2.5.4:tampaknya berfungsi, tetapi tidak disengaja dan tidak dijamin berfungsi.
Sebelum diperbaiki di 2.6 (dengan komit ini ), GNU
grep
telah mengabaikan bahwa fungsi pencarian pcre yang digunakannya akan cocok dengan seluruh buffer yang saat ini diprosesgrep
, menyebabkan segala macam perilaku mengejutkan. Contohnya:akan cocok dengan file yang berisi:
Ini cocok dengan:
Tapi ini:
Atau:
tidak mau (karena
1\n2\n
melintasi dua buffer diproses olehgrep
).Perilaku itu akhirnya didokumentasikan:
Setelah diperbaiki di 2.6, dokumentasi tidak diubah (saya pernah melaporkannya di sana ).
sumber
exit
dan-exec \;
bukannya nextfile?awk
per file. Anda ingin melakukannya hanya jika Andaawk
tidak mendukungnextfile
dan Anda memiliki sebagian besar file yang besar dan memiliki garis yang cocok pada awal file.-z
dengan-P
. Tidak ada\N
tanpa-P
, Anda harus menulisnya$'[\01-\011\013-\0377]'
yang hanya akan berfungsi di C locales (lihat thread.gmane.org/gmane.comp.gnu.grep.bugs/5187 )Dengan
awk
:Ini akan mencetak konten file jika ada baris berurutan yang dimulai dengan a
C
. Ekspresi(p ~ /^C/ && $1 ~ /^C/)
akan melihat baris yang berurutan dalam file dan akan mengevaluasi true jika karakter pertama di kedua cocokC
. Jika itu masalahnya, garis akan dicetak.Untuk menemukan semua file yang memiliki pola seperti itu, Anda dapat menjalankan awk di atas melalui
find
perintah:Dalam perintah ini,
find
+exec
akan melalui masing-masing file dan melakukanawk
penyaringan yang sama pada setiap file dan mencetak namanya melaluiFILENAME
jika ekspresi awk dievaluasi menjadi true. Untuk menghindari pencetakanFILENAME
beberapa kali untuk satu file dengan banyak kecocokan,exit
pernyataan tersebut digunakan (terima kasih @terdon).sumber
C
flag
, hanyaexit
saja. Dengan begitu, Anda tidak perlu terus memproses file setelah kecocokan ditemukan.Opsi lain dengan GNU
sed
:Untuk satu file:
(meskipun itu juga akan melaporkan file yang tidak dapat dibaca).
Untuk
find
:Masalah dengan file yang tidak dapat dibaca yang sedang dicetak dapat dihindari dengan menuliskannya:
sumber
sed -n '$q1;/^C/{n;/^C/q}'
?$q1
- memaksa sed untuk berhenti dengan kesalahan jika pola tidak ditemukan. Itu juga akan selesai dengan kesalahan jika ada sesuatu yang salah dengan file (itu tidak dapat dibaca atau rusak). Jadi ia akan keluar dengan status keluar 0 hanya jika ditemukan pola dan akan diteruskan untuk dicetak. Bagian dengan/^C/{n;/^C/q
ini cukup sederhana. Jika ia menemukan string yang dimulai dengan C, ia akan membaca baris berikutnya dan jika itu juga dimulai dengan C, ia akan berhenti dengan status keluar nol.Dengan asumsi file Anda cukup kecil untuk dibaca ke dalam memori:
Penjelasan:
000
: ditetapkan\n\n
sebagai pemisah rekaman, ini mengaktifkan mode paragraf yang akan memperlakukan paragraf (dipisahkan oleh baris baru berurutan) sebagai baris tunggal.-ne
: terapkan skrip yang diberikan sebagai argumen-e
untuk setiap baris file input.$ARGV
: adalah file yang sedang diproses/^C[^\n]*\nC/
: cocokkanC
di awal baris (lihat deskripsism
pengubah di bawah ini untuk alasan mengapa ini bekerja di sini) diikuti oleh 0 atau lebih karakter non-baris baru, baris baru dan kemudian C. lainnya Dengan kata lain, cari baris berturut-turut dimulai denganC
. *//sm
: pengubah pertandingan ini (seperti yang didokumentasikan [di sini]):Anda juga bisa melakukan sesuatu yang jelek seperti:
Di sini,
perl
kode menggantikan baris baru dengan%%
begitu, dengan asumsi Anda tidak memiliki%%
dalam file input Anda (besar jika tentu saja),grep
akan cocok dengan baris berturut-turut dimulai denganC
.sumber
LARUTAN:
DEMO:
Pertama, kami akan membuat basis tes:
Di atas membuat 26 file
/tmp
bernamafile1-26
. Di setiap file ada 27 atau 28 baris dimulai dengan hurufa-z
dan diikuti oleh sisa alfabet. Setiap file ke-3 berisi dua baris berturut-turut di mana karakter pertama diduplikasi.SAMPEL:
Dan ketika saya berubah:
untuk:
Saya mendapat...
KELUARAN:
Jadi, secara singkat, solusinya bekerja seperti ini:
sumber
Script ini menggunakan
grep
dancut
untuk mendapatkan nomor baris dari baris yang cocok, dan memeriksa dua nomor berurutan. File diasumsikan nama file yang valid diberikan sebagai argumen pertama ke skrip:sumber