Saya ingin menemukan semua baris dalam beberapa file yang cocok dengan salah satu dari dua pola. Saya mencoba menemukan pola yang saya cari dengan mengetik
grep (foo|bar) *.txt
tetapi shell mengartikannya |
sebagai pipa dan mengeluh kapanbar
tidak dapat dieksekusi.
Bagaimana saya bisa mendapatkan beberapa pola dalam kumpulan file yang sama?
Jawaban:
Pertama, Anda perlu melindungi pola dari ekspansi oleh shell. Cara termudah untuk melakukannya adalah dengan menempatkan tanda kutip tunggal di sekitarnya. Kutipan tunggal mencegah perluasan apa pun di antara mereka (termasuk backslash); satu-satunya hal yang tidak dapat Anda lakukan adalah memiliki tanda kutip tunggal dalam pola.
Jika Anda memang membutuhkan satu kutipan, Anda dapat menuliskannya sebagai
'\''
(string akhir literal, kutipan literal, string terbuka literal).Kedua, grep mendukung dua sintaks untuk pola. Sintaks default yang lama ( ekspresi reguler dasar ) tidak mendukung
|
operator alternation ( ), meskipun beberapa versi memilikinya sebagai ekstensi, tetapi ditulis dengan backslash.Cara portabel adalah dengan menggunakan sintaks yang lebih baru, ekspresi reguler yang diperluas . Anda harus melewati
-E
opsigrep
untuk memilihnya. Di Linux, Anda juga bisa mengetikegrep
alih-alihgrep -E
(di unices lain, Anda bisa menjadikannya sebagai alias).Kemungkinan lain ketika Anda hanya mencari salah satu dari beberapa pola (sebagai lawan membangun pola kompleks menggunakan disjungsi) adalah meneruskan beberapa pola
grep
. Anda dapat melakukan ini dengan mendahului setiap pola dengan-e
opsi.sumber
fgrep
ataugrep -F
, untuk pola kecil perbedaannya dapat diabaikan tetapi seiring bertambahnya waktu, manfaatnya mulai terlihat ...grep -F
memiliki manfaat kinerja aktual tergantung pada implementasi grep: beberapa dari mereka menerapkan algoritma yang sama, sehingga-F
membuat perbedaan hanya pada waktu yang dihabiskan untuk menguraikan pola dan tidak untuk pencarian waktu. GNU grep tidak lebih cepat dengan-F
, misalnya (ia juga memiliki bug yang membuatgrep -F
lebih lambat di lokal multibyte - pola konstan yang sama dengangrep
sebenarnya jauh lebih cepat!). Di sisi lain BusyBox grep memang mendapat banyak manfaat dari-F
pada file besar.egrep
sebelumgrep -E
. Ini bukan spesifik GNU (tentu tidak ada hubungannya dengan Linux). Sebenarnya, Anda masih akan menemukan sistem seperti Solaris di mana standarnyagrep
masih tidak mendukung-E
.atau
secara selektif mengutip halaman manual gnu-grep:
(...)
Pada awalnya saya tidak membaca lebih lanjut, jadi saya tidak mengenali perbedaan halus:
Saya selalu menggunakan egrep dan orangtua yang tidak perlu, karena saya belajar dari contoh. Sekarang saya belajar sesuatu yang baru. :)
sumber
Seperti kata TC1,
-F
sepertinya ini adalah opsi yang bisa digunakan:sumber
Pertama, Anda perlu menggunakan tanda kutip untuk karakter khusus. Kedua, meskipun demikian,
grep
tidak akan mengerti pergantian secara langsung; Anda harus menggunakanegrep
, atau (grep
hanya dengan GNU )grep -E
.(Kurung tidak perlu kecuali jika pergantian adalah bagian dari regex yang lebih besar.)
sumber
grep -E
lebih standar daripadaegrep
.Jika Anda tidak memerlukan ekspresi reguler, ini jauh lebih cepat untuk digunakan
fgrep
ataugrep -F
dengan beberapa parameter e, seperti ini:fgrep
(Ataugrep -F
) jauh lebih cepat daripada grep biasa karena ia mencari string tetap daripada ekspresi reguler.sumber
fgrep
itu sudah usang.Anda dapat mencoba perintah di bawah ini untuk mendapatkan hasilnya:
sumber
Cara murah dan ceria untuk memahami berbagai pola:
sumber
-f
opsi grep mengambil file dengan beberapa pola. Alih-alih membuat file sementara (yang mungkin Anda lupa hapus setelahnya), cukup gunakan subtitusi proses shell:grep -f <(echo foo; echo bar) *.txt
Pipe (
|
) adalah karakter shell khusus, jadi ia perlu diloloskan (\|
) atau dikutip sesuai manual (man bash
):Lihat: Karakter mana yang harus diloloskan di Bash?
Berikut adalah beberapa contoh (menggunakan alat yang belum disebutkan):
Menggunakan
ripgrep
:rg "foo|bar" *.txt
rg -e foo -e bar *.txt
Menggunakan
git grep
:git grep --no-index -e foo --or -e bar
Catatan: Ini juga mendukung ekspresi Boolean seperti
--and
,--or
dan--not
.Untuk DAN operasi per baris, lihat: Bagaimana menjalankan grep dengan banyak pola DAN?
Untuk DAN operasi per file, lihat: Bagaimana memeriksa semua string atau regex yang ada di file?
sumber
Saya memiliki akses log di mana tanggal diformat dengan bodoh: [30 / Jun / 2013: 08: 00: 45 +0200]
Tapi saya perlu menampilkannya sebagai: 30 / Jun / 2013 08:00:45
Masalahnya adalah bahwa menggunakan "ATAU" dalam pernyataan grep saya, saya menerima dua ekspresi kecocokan pada dua baris terpisah.
Ini solusinya:
sumber
TL; DR: jika Anda ingin melakukan lebih banyak hal setelah mencocokkan salah satu dari beberapa pola, lampirkan seperti pada
\(pattern1\|pattern2\)
contoh: Saya ingin menemukan semua tempat di mana variabel yang berisi nama 'tanggal' didefinisikan sebagai String atau int. (mis. "int cronDate =" atau "String textFormattedDateStamp ="):
Dengan
grep -E
, Anda tidak perlu melepaskan kurung atau pipa, yaitu,grep -E '(int|String) [a-zA-Z_]*date[a-zA-Z_]* ='
sumber
Ini bekerja untuk saya
sumber
Ada beberapa cara untuk melakukan ini.
grep 'foo\|bar' *.txt
egrep 'foo|bar' *.txt
find . -maxdepth 1 -type f -name "*.txt" | xargs grep 'foo\|bar'
find . -maxdepth 1 -type f -name "*.txt" | xargs egrep 'foo|bar'
Opsi ke-3 dan ke-4 hanya akan menangkap file dan menghindari direktori memiliki
.txt
nama mereka.Jadi, sesuai kasus penggunaan Anda, Anda dapat menggunakan salah satu opsi yang disebutkan di atas.
Terima kasih!!
sumber
untuk menambahkan jawaban @ geekosaur , jika Anda memiliki beberapa pola yang juga berisi tab dan ruang Anda menggunakan perintah berikut
di mana
[[:blank:]]
kelas karakter RE yang mewakili spasi atau karakter tabsumber