ambil dan lepas tanda dolar

31

Saya ingin tahu file mana yang memiliki string $Id$.

grep \$Id\$  my_dir/mylist_of_files

mengembalikan 0 kejadian.

Saya menemukan bahwa saya harus menggunakan

grep \$Id$ my_dir/mylist_of_files

Lalu saya melihat bahwa $Idberwarna pada output, yaitu sudah cocok.

Bagaimana saya bisa mencocokkan yang kedua $dan mengapa tidak \$Id\$berhasil.

Tidak masalah apakah karakter kedua $adalah karakter terakhir atau bukan.

Saya menggunakan grep2.9.


Sebelum memposting pertanyaan saya, saya menggunakan google ...

Saya menemukan jawaban

Untuk mencari $ (tanda dolar) di file bernama test2, masukkan:

grep \\ $ test2

Karakter \\ (double backslash) diperlukan untuk memaksa shell untuk melewatkan \ $ (backslash tunggal, tanda dolar) ke perintah grep. Karakter \ (backslash tunggal) memberi tahu perintah grep untuk memperlakukan karakter berikut (dalam contoh ini $) sebagai karakter literal daripada karakter ekspresi. Gunakan perintah fgrep untuk menghindari keharusan menggunakan karakter escape seperti backslash.

tapi saya tidak mengerti mengapa itu grep \$Idberhasil dan mengapa grep \\$Id\\$tidak.

Aku sedikit bingung...

Luc M
sumber

Jawaban:

25

Ada 2 masalah terpisah di sini.

  1. grepmenggunakan Basic Regular Expressions (BRE), dan $merupakan karakter khusus dalam BRE hanya pada akhir ekspresi. Konsekuensi dari ini adalah bahwa 2 instance $in $Id$tidak sama. Yang pertama adalah karakter normal dan yang kedua adalah jangkar yang cocok dengan ujung garis. Untuk membuat $pertandingan kedua menjadi literal, $Anda harus melarikan diri backslash darinya, yaitu $Id\$. Lolos dari yang pertama $juga berfungsi :, \$Id\$dan saya lebih suka ini karena terlihat lebih konsisten

  2. Ada dua mekanisme melarikan diri / mengutip yang sama sekali tidak terkait yang bekerja di sini: shell quoting dan regex backslash quoting. Masalahnya adalah banyak karakter yang menggunakan ekspresi reguler khusus untuk shell juga, dan di atas itu karakter escape regex, backslash, juga karakter mengutip shell. Inilah sebabnya mengapa Anda sering melihat kekacauan yang melibatkan backslash ganda, tetapi saya tidak menyarankan menggunakan backslash untuk shell mengutip ekspresi reguler karena itu tidak terlalu mudah dibaca.

    Alih-alih, cara paling sederhana untuk melakukan ini adalah dengan terlebih dahulu memasukkan seluruh regex Anda ke dalam tanda kutip tunggal seperti pada 'regex'. Kutipan tunggal adalah bentuk terkuat dari kutipan yang dimiliki shell, jadi selama regex Anda tidak mengandung kutipan tunggal, Anda tidak perlu lagi khawatir tentang penawaran shell dan dapat fokus pada sintaks BRE murni.

Jadi, menerapkan ini kembali ke contoh asli Anda, mari kita melemparkan regex yang benar ( \$Id\$) di dalam tanda kutip tunggal. Berikut ini harus melakukan apa yang Anda inginkan:

grep '\$Id\$' my_dir/my_file

Alasannya \$Id\$tidak berhasil adalah karena setelah penghapusan kutipan shell (cara yang lebih tepat untuk mengatakan kutipan shell) diterapkan, regex yang grepmelihatnya adalah $Id$. Seperti yang dijelaskan dalam (1.), regex ini cocok dengan literal $Idhanya pada akhir baris karena yang pertama $adalah literal sedangkan yang kedua adalah karakter jangkar khusus.

¹ Catat juga bahwa jika Anda pernah beralih ke Extended Regular Expressions (ERE), mis. Jika Anda memutuskan untuk menggunakan egrep(atau grep -E), $karakternya selalu spesial. Dalam ERE's $Id$tidak akan pernah cocok dengan apa pun karena Anda tidak dapat memiliki karakter setelah akhir baris, jadi \$Id\$akan menjadi satu-satunya cara untuk pergi.

jw013
sumber
3
Untuk menghindari grep menafsirkan parameter pertama sebagai ekspresi reguler, Anda juga dapat melakukannya grep -F '$Id$'.
jfg956
Dalam shell saya (bash 4.3.42) grep '$Id\$' ...dan grep \$Id\\$ ...bekerja
nitsas
2
Dan jika ini adalah perintah pada makefile, Anda juga harus melarikan diri $dengan sebelumnya $: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune
-2

Untuk mencari $Id$file: Anda dapat menggunakan:grep '\$id*' filename

Bala
sumber
2
Itu akan cocok dengan apa pun yang dimulai dengan $id, jadi $ideamisalnya juga, bukan hanya $id$.
terdon