Jaka jest różnica między „* .pl” a * .pl w grep? Dlaczego cytowanie zmienia wynik?

10

Jaka jest różnica pomiędzy:
grep "string" . -r --include *.pl

i

grep "string" . -r --include "*.pl"

Ten ostatni zawiera pliki w podkatalogu, podczas gdy ten pierwszy nie. Dlaczego?

Jim
źródło
Różnica nie tkwi w grep; jest w skorupce. grepnigdy nie widzi cytatów.
Wildcard

Odpowiedzi:

17

*(Gwiazda lub gwiazdka) to specjalny znak, który jest (zazwyczaj) interpretowane przez powłokę przed podaniem komendy. Jest (zwykle) rozszerzony na wszystkie nazwy plików oprócz tych z wiodącymi kropkami. Aby uzyskać więcej informacji, zobacz instrukcję bash dotyczącą dopasowywania wzorów .

Umieszczona w cudzysłowie gwiazda nie będzie interpretowana przez powłokę i zostanie przekazana do polecenia dosłownie.


Przykłady wyjaśnione. Cytowany:

grep "string" . -r --include "*.pl"

Tutaj grepotrzymasz opcję --includez argumentem *.pl. Jest to ciąg 4 znaków, w którym *znak jest pierwszym znakiem. Wszystko, co grepdzieje się z tym ciągiem, zależy całkowicie grep. W tym przypadku --includeoznacza rozważenie tylko plików pasujących do wzorca *.pl.

AFAIK za sceną gnu grep używa tego samego wzorca dopasowującego lib jak gnu bash.

Nie cytowany:

grep "string" . -r --include *.pl

Tutaj powłoka najpierw rozszerzy wzór *.pldo wszystkich nazw plików kończących się na .pl. Załóżmy, że istnieją pliki foo.pl, bar.pla baz.pl. Po rozwinięciu wiersz poleceń wygląda następująco:

grep "string" . -r --include foo.pl bar.pl baz.pl

Tutaj grepotrzymasz opcję --includez argumentem foo.pl, a następnie opcje bar.pli baz.pl. --include foo.ploznacza rozważenie tylko plików pasujących do wzorca foo.pl. Ponieważ we wzorcu nie ma symboli wieloznacznych, jedynym pasującym plikiem będzie plik o nazwie foo.pl.

Opcje bar.pli baz.plśrodki grep będą również wyszukiwać w tych plikach, ale ponieważ nie pasują do wzorca foo.pl, zostaną zignorowane.

lesmana
źródło
To świetna obserwacja. Zawsze zastanawiałem się, dlaczego grep -rwydawało się to niespójne, ale nigdy nie zauważyłem, że było to tylko wtedy, gdy użyłem *.
j883376
6

Różnica polega na tym, że jeśli nie zacytujesz wzorca ( *.pl), zostanie on rozwinięty przez powłokę. Na przykład, jeśli uruchomisz swój grepw katalogu, który zawiera plik o nazwie foo.pl, ponieważ *pljest on rozwijany przez powłokę, tak grepnaprawdę widzi:

grep "string" . -r --include foo.pl

Ponieważ nakazujesz, aby zawierał foo.pltylko, przeszuka tylko ten jeden plik.

Jeśli zacytujesz swój wzór, powłoka go nie rozwinie i grepotrzyma prawidłowe polecenie, a mianowicie

 grep "string" . -r --include *pl
terdon
źródło
peoplnie zostanie rozszerzony o *.pl.
unxnut
@unxnut good point, zredagowano odpowiedź.
terdon