Bagaimana cara membuat grep hanya cocok jika seluruh baris cocok?


104

Saya punya ini:

$ cat a.tmp
ABB.log
ABB.log.122
ABB.log.123

Saya ingin menemukan yang sama persis dengan ABB.log.

Tapi saat aku melakukannya

$ grep -w ABB.log a.tmp
ABB.log
ABB.log.122
ABB.log.123

itu menunjukkan semuanya.

Bisakah saya mendapatkan apa yang saya inginkan menggunakan grep?

Jawaban:


105

Cukup tentukan jangkar regexp.

grep '^ABB\.log$' a.tmp

2
Baik jangkar (^ dan $) diperlukan.
pengguna562374

2
Bagus! Dan jika saya menggunakan regex untuk pencocokan dari file? "pola grep -f a.tmp" ??
hijau69

@ green69 Terlambat beberapa tahun, tetapi Anda dapat menggunakan sed untuk menambahkan jangkar sebelum meneruskan pola ke grep:sed -r "s/^(.*)$/^\1$/" patterns.txt | egrep -f - a.tmp
Randoms

155
grep -Fx ABB.log a.tmp

Dari halaman manual grep:

-F, --fixed-strings
Tafsirkan POLA sebagai (daftar) string tetap
-x, --line-regexp
Pilih hanya kecocokan yang sama persis dengan seluruh baris.


2
tidak dapat menggunakan -F sayangnya.
Johnyy

@Johnyy Tidak -F? Apakah Anda di Solaris? Jika demikian gunakan/usr/xpg4/bin/grep
Scrutinizer

9
Saya menggunakan grepdi dalam skrip bash dan opsi ini lebih baik daripada menggunakan ekspresi reguler seperti yang disarankan dalam jawaban yang diterima. Karena saya memiliki beberapa karakter khusus di dalam variabel yang saya cari (suka .) dan saya tidak perlu menghindarinya saat menggunakan perintah.
Gustavo Straube

1
jawaban terbaik IMO karena memungkinkan karakter khusus tanpa melarikan diri
ReneGAED

1
Ini lebih baik karena juga bekerja dengan variabel.
ybenjira

23

Inilah yang saya lakukan, meskipun menggunakan jangkar adalah cara terbaik:

grep -w "ABB.log " a.tmp

Seperti ini .. ini akan mengembalikan Pertandingan baris pertama
user765443

1
Ini membutuhkan spasi setelahnya ABB.log, yang bukan kasus umum, yaitu akan gagal sebagian besar waktu.
Jahid

3

Sebagian besar saran akan gagal jika hanya ada satu spasi di depan atau di belakang, yang penting jika file sedang diedit secara manual. Ini akan membuatnya kurang rentan dalam kasus itu:

grep '^[[:blank:]]*ABB\.log[[:blank:]]*$' a.tmp

Loop sementara-baca sederhana di shell akan melakukan ini secara implisit:

while read file
do 
  case $file in
    (ABB.log) printf "%s\n" "$file"
  esac
done < a.tmp


1

Saya bermaksud menambahkan beberapa penjelasan tambahan mengenai upaya OP dan jawaban lainnya juga.

Anda juga dapat menggunakan solusi John Kugelmans seperti ini:

grep -x "ABB\.log" a.tmp

mengutip string dan meng-escape titik ( .) membuatnya tidak lagi membutuhkan -Fflag.

Anda perlu meng-escape .(titik) (karena cocok dengan karakter apa pun (tidak hanya .) jika tidak di-escape) atau gunakan -Fflag dengan grep. -Fflag menjadikannya string tetap (bukan regex).

Jika Anda tidak mengutip string, Anda mungkin perlu garis miring terbalik ganda untuk mengosongkan titik ( .):

grep -x ABB\\.log a.tmp


Uji:

$ echo "ABBElog"|grep -x  ABB.log
ABBElog #matched !!!
$ echo "ABBElog"|grep -x  "ABB\.log"
#returns empty string, no match


catatan:

  1. -x kekuatan untuk mencocokkan seluruh garis.
  2. Jawaban menggunakan non escaped .tanpa -Fflag salah.
  3. Anda dapat menghindari -xpengalihan dengan membungkus string pola Anda dengan ^dan $. Dalam hal ini, pastikan Anda tidak menggunakan -F, alih-alih escape ., karena -Fakan mencegah interpretasi regex dari ^dan $.


EDIT: (Menambahkan penjelasan tambahan tentang @hakre):

Jika Anda ingin mencocokkan string yang dimulai dengan -, maka Anda harus menggunakan --grep. Apapun yang mengikuti --akan diambil sebagai masukan (bukan pilihan).

Contoh:

echo -f |grep -- "-f"     # where grep "-f" will show error
echo -f |grep -F -- "-f"  # whre grep -F "-f" will show error
grep "pat" -- "-file"     # grep "pat" "-file" won't work. -file is the filename

Apakah Anda benar-benar mengalami bahwa -F hilang dalam kasus Anda? Jika demikian, dapatkah Anda mengatakan kasus apa itu?
hakre

@hakre Apakah Anda membaca jawaban saya sepenuhnya? Saya menjelaskan (cukup jelas) mengapa -Ftidak diperlukan jika .lolos dengan benar.
Jahid

Tentu. Oke, saya hanya bertanya: Apakah -Ftersedia saat Anda menulis ini? Jika tidak, sistem mana yang Anda gunakan? Sejauh ini saya tidak dapat menemukan informasi itu dalam jawaban Anda, yang bahkan sekarang adalah kasus ketika saya membacanya lagi. Jadi sangat yakin, saya membaca jawaban Anda sepenuhnya setidaknya dua kali. ;)
hakre

@hakre Tentu saja -Ftersedia. (Saya memang mengatakan: "atau gunakan -Fbendera dengan grep")
Jahid

Terima kasih atas wawasannya. Hanya satu pertanyaan kecil yang tersisa: Jika -Fjawabannya, mengapa repot-repot melarikan diri? Apa pendapatmu tentang itu?
hakre

1

Ini bekerja dengan baik untuk saya ketika mencoba melakukan sesuatu yang serupa:

grep -F ABB.log a.tmp

-1
    $ cat venky
    ABB.log
    ABB.log.122
    ABB.log.123

    $ cat venky | grep "ABB.log" | grep -v "ABB.log\."
    ABB.log
    $

    $ cat venky | grep "ABB.log.122" | grep -v "ABB.log.122\."
    ABB.log.122
    $

1
Ini juga akan mencocokkan file yang diakhiri dengan ABB.log dan titik-titik tersebut harus di-escape.
Scrutinizer

-1

Bekerja untuk saya :

grep "\bsearch_word\b" text_file > output.txt  

\b menunjukkan / menetapkan batas.

Sepertinya bekerja cukup cepat


Ini juga cocok dengan setiap baris yang berisi search_worddipisahkan oleh batas kata. Misalnya, ini akan cocok dengan baris, "foo search_word bar".
Rohan Singh

-2

Ini dengan HPUX, jika konten file memiliki spasi antar kata, gunakan ini:

egrep "[[:space:]]ABC\.log[[:space:]]" a.tmp


OP ingin mencocokkan seluruh baris, bukan kata yang dipisahkan spasi di dalam baris.
Keith Thompson


-3

Saya membutuhkan fitur ini, tetapi juga ingin memastikan bahwa saya tidak mengembalikan baris dengan awalan sebelum ABB.log:

  • ABB.log
  • ABB.log.122
  • ABB.log.123
  • 123ABB.log

grep "\WABB.log$" -w a.tmp

Ini hanya akan cocok jika awalannya \Wterpenuhi, yaitu karakter non spasi kosong, jadi xABBxlog.
bschlueter
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.