grep i ucieczka od znaku dolara

31

Chcę wiedzieć, które pliki mają ciąg $Id$.

grep \$Id\$  my_dir/mylist_of_files

zwraca 0 wystąpień.

Odkryłem, że muszę użyć

grep \$Id$ my_dir/mylist_of_files

Potem widzę, że $Idkolor jest wyjściowy, tzn. Został dopasowany.

Jak mogłem dopasować drugi $i dlaczego nie \$Id\$działa.

Nie ma znaczenia, czy drugi $to ostatni znak, czy nie.

Używam grep2.9.


Przed opublikowaniem pytania użyłem google ...

Znalazłem odpowiedź

Aby wyszukać $ (znak dolara) w pliku o nazwie test2, wpisz:

grep \\ $ test2

Znaki \\ (podwójny odwrotny ukośnik) są konieczne, aby wymusić na powłoce przekazanie \ $ (pojedynczy odwrotny ukośnik, znak dolara) do polecenia grep. Znak \ (pojedynczy ukośnik odwrotny) mówi komendzie grep, aby traktowała następujący znak (w tym przykładzie $) jako znak dosłowny, a nie znak wyrażenia. Użyj polecenia fgrep, aby uniknąć konieczności używania znaków specjalnych, takich jak ukośnik odwrotny.

ale nie rozumiem, dlaczego grep \$Iddziała, a dlaczego grep \\$Id\\$nie.

Jestem trochę zmieszany...

Luc M.
źródło

Odpowiedzi:

25

Są tutaj 2 osobne problemy.

  1. grepużywa podstawowych wyrażeń regularnych (BRE) i $jest znakiem specjalnym w BRE tylko na końcu wyrażenia. Konsekwencją tego jest to, że 2 wystąpienia $in $Id$nie są równe. Pierwszy to normalny znak, a drugi to kotwica pasująca do końca linii. Aby drugi $mecz był dosłowny $, musisz uciec z ukośnika odwrotnego, tzn $Id\$. Ucieczka od pierwszego $działa również: \$Id\$i wolę to, ponieważ wygląda bardziej spójnie .¹

  2. Działają tutaj dwa całkowicie niezwiązane mechanizmy ucieczki / cytowania: cytowanie z powłoki i cytowanie z odwrotnym ukośnikiem. Problemem jest to, że wiele znaków, które używają wyrażeń regularnych, jest również specjalnych dla powłoki, a ponadto znak ucieczki wyrażenia regularnego, odwrotny ukośnik, jest również znakiem cytowania powłoki. To dlatego często widzisz mesy zawierające podwójne ukośniki odwrotne, ale nie polecam używania ukośników odwrotnych do wyrażeń regularnych powłoki, ponieważ nie jest to zbyt czytelne.

    Zamiast tego najprostszym sposobem na to jest umieszczenie całego wyrażenia regularnego w pojedynczych cudzysłowach jak w 'regex'. Pojedynczy cytat jest najsilniejszą formą cytowania powłoki, więc dopóki regex nie zawiera pojedynczych cytatów, nie musisz się już martwić o cytowanie powłoki i możesz skupić się na czystej składni BRE.

Wracając do oryginalnego przykładu, wrzućmy poprawne wyrażenie regularne ( \$Id\$) do pojedynczych cudzysłowów. Następujące czynności powinny robić, co chcesz:

grep '\$Id\$' my_dir/my_file

Powód \$Id\$nie działa, ponieważ po usunięciu cudzysłowu powłoki (bardziej poprawny sposób powiedzenia cytowania powłoki) jest regex, który grepwidzi $Id$. Jak wyjaśniono w (1.), wyrażenie regularne dopasowuje literał $Idtylko na końcu linii, ponieważ pierwszy $jest dosłowny, a drugi jest specjalnym znakiem kotwicy.

¹ Pamiętaj również, że jeśli kiedykolwiek przełączysz się na Rozszerzone wyrażenia regularne (ERE), np. Jeśli zdecydujesz się użyć egrep(lub grep -E), $postać jest zawsze wyjątkowa. W ERE $Id$nigdy by nic nie pasowało, ponieważ nie możesz mieć znaków po zakończeniu linii, więc \$Id\$byłby to jedyny sposób.

jw013
źródło
3
Aby uniknąć interpretacji grep jego pierwszego parametru jako wyrażenia regularnego, możesz to zrobić grep -F '$Id$'.
jfg956
W mojej powłoce (bash 4.3.42) grep '$Id\$' ...i grep \$Id\\$ ...pracy
nitsas
2
A jeśli jest to komenda w makefile, należy również uciec $z poprzednich $: grep '$$Id\$$'. stackoverflow.com/a/2382810/2097284
Camille Goudeseune
-2

Aby wyszukać $Id$w pliku: możesz użyć:grep '\$id*' filename

Bala
źródło
2
To pasuje do wszystkiego, począwszy od $id, więc $ideana przykład, nie tylko $id$.
terdon