*
ma specjalne znaczenie zarówno jako znak globowania powłoki („symbol wieloznaczny”), jak i metaznak wyrażenia regularnego . Musisz wziąć to pod uwagę, ale jeśli zacytujesz swoje wyrażenie regularne, możesz zapobiec specjalnemu traktowaniu go przez powłokę i upewnić się, że przekazuje ją bez zmian grep
. Chociaż rodzaj podobny koncepcyjnie, jakie *
środki do powłoki jest zupełnie inny od tego, co to znaczy grep
.
Najpierw powłoka traktuje *
jak symbol wieloznaczny.
Powiedziałeś:
To, czy wyrażenie jest ujęte w cudzysłów, nie ma znaczenia.
To zależy od tego, jakie pliki istnieją w jakimkolwiek katalogu, w którym się znajdujesz po uruchomieniu polecenia. W przypadku wzorców zawierających separator katalogów /
może to zależeć od plików istniejących w całym systemie. Powinieneś zawsze cytować wyrażenia regularne dla - grep
a pojedyncze cudzysłowy są zwykle najlepsze - chyba że jesteś pewien, że nie masz nic przeciwko dziewięciu rodzajom potencjalnie zaskakujących transformacji, które powłoka wykonuje w przeciwnym razie przed wykonaniem grep
polecenia.
Gdy powłoka napotka *
znak, który nie jest cytowany , oznacza to, że oznacza „zero lub więcej dowolnego znaku” i zastępuje słowo, które go zawiera, listą nazw plików pasujących do wzorca. ( Nazwy plików rozpoczynające się od .
są wykluczone - chyba że sam wzorzec zaczyna się od .
lub nie skonfigurowałeś powłoki tak, aby i tak je obejmował.) Jest to znane jako globbing - a także przez rozszerzenie nazw plików i rozszerzenie nazw ścieżek .
Efekt z grep
zazwyczaj będzie to pierwszy pasujący plik jest traktowane jako wyrażenie regularne - nawet jeśli byłoby to dość oczywiste dla czytelnika ludzkiej, że jest nie oznaczało, jako wyrażenie regularne - gdy wszystkie inne wymienione nazwy plików automatycznie od glob są traktowane jako pliki, w których można wyszukiwać dopasowania. (Nie widzisz listy - jest ona nieprzezroczysta grep
.) Właściwie nigdy nie chcesz, aby tak się stało.
Powodem, dla którego czasami nie jest to problem - aw twoim konkretnym przypadku, przynajmniej do tej pory , nie było - jest to, że *
pozostaniesz sam, jeśli wszystkie poniższe warunki są prawdziwe :
Nie było żadnych plików, których nazwy pasują do siebie. ... Lub wyłączyłeś globowanie w swojej powłoce, zwykle za pomocą set -f
lub równoważnego set -o noglob
. Ale jest to rzadkie i prawdopodobnie wiedziałbyś, że to zrobiłeś.
Używasz powłoki, której domyślnym zachowaniem jest pozostawienie w *
spokoju, gdy nie ma pasujących nazw plików. Tak jest w przypadku Bash, którego prawdopodobnie używasz, ale nie we wszystkich powłokach w stylu Bourne'a. (Domyślne zachowanie w popularnej powłoce Zsh, na przykład, polega na tym, że globusy albo (a) rozwijają się, albo (b) generują błąd.) ... Lub zmieniłeś to zachowanie swojej powłoki - jak to się robi, zmienia się w poprzek muszli.
W przeciwnym razie nie powiedziałeś swojej powłoce, aby zezwoliła na zastąpienie globów niczym, gdy nie ma pasujących plików, ani nie powiodła się z komunikatem o błędzie w tej sytuacji. W Bash można to zrobić, włączając odpowiednio opcjęnullglob
lub failglob
shell .
Czasami możesz polegać na # 2 i # 3, ale rzadko możesz polegać na # 1. grep
Komenda z nienotowanego wzór, który działa teraz może przestać działać, gdy masz różne pliki lub po uruchomieniu go z innego miejsca. Podaj wyrażenie regularne, a problem zniknie.
Wtedy gdy grep
traktuje dowodzenia *
jako kwantyfikator.
Inne odpowiedzi - takie jak Sergiy Kolodyazhnyy i Kos - również odnoszą się do tego aspektu tego pytania na nieco inne sposoby. Zachęcam więc tych, którzy jeszcze ich nie czytali, do zrobienia tego przed lub po przeczytaniu reszty tej odpowiedzi.
Zakładając, że *
robi się grep - co powinno zapewnić cytowanie - grep
oznacza to, że poprzedzający go element może wystąpić dowolną liczbę razy , zamiast musieć występować dokładnie raz . To może się zdarzyć raz. Lub może wcale nie być obecny. Lub można to powtórzyć. Tekst pasujący do którejkolwiek z tych możliwości zostanie dopasowany.
Co rozumiem przez „przedmiot”?
Pojedyncza postać . Od b
meczów dosłownym b
, b*
zero lub więcej b
s, co ab*c
odpowiada ac
, abc
, abbc
, abbbc
, itd.
Podobnie, ponieważ .
dopasowuje dowolny znak , .*
zero lub więcej znaków 1 , co a.*c
meczów ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, nawet acccccchjckhcc
, itp Or
Klasa postaci . Ponieważ [xy]
mecze x
lub y
, [xy]*
dopasowuje zero lub więcej znaków, gdzie każdy z nich jest albo x
albo y
, co p[xy]*q
pasuje pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
, itd.
Odnosi się to również do skrótowym formy z klas postaci, takich jak \w
, \W
, \s
, i \S
. Ponieważ \w
pasuje do dowolnego znaku słowa, \w*
dopasowuje zero lub więcej znaków słowa. Lub
Grupy . Od \(bar\)
meczów bar
, \(bar\)*
zero lub więcej bar
s, co foo\(bar\)*baz
odpowiada foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
, itd.
Za pomocą opcji -E
lub traktuje wyrażenie regularne odpowiednio jako ERE lub PCRE , a nie jako BRE , a następnie grupy są otoczone przez zamiast , więc wtedy użyjesz zamiast i zamiast .-P
grep
(
)
\(
\)
(bar)
\(bar\)
foo(bar)baz
foo\(bar\)baz
man grep
podaje na końcu przystępne wyjaśnienie składni BRE i ERE, a także listę wszystkich opcji wiersza poleceń, które grep
akceptuje na początku. Polecam tę stronę podręcznika jako zasób, a także dokumentację GNU Grep i tę stronę z samouczkami / materiałami referencyjnymi (do której linkowałem na wielu stronach powyżej).
Do testowania i uczenia się grep
zalecam nazywanie go wzorcem, ale bez nazwy pliku. Następnie pobiera dane wejściowe z terminala. Wpisz linie; linie, które odbijają się echem, to te, które zawierały tekst pasujący do wzorca. Aby wyjść, naciśnij Ctrl+ Dna początku linii, która sygnalizuje koniec wejścia. (Lub możesz nacisnąć Ctrl+ Cjak w większości programów wiersza poleceń.) Na przykład:
grep 'This.*String'
Jeśli użyjesz --color
flagi, grep
podświetli określone części linii, które pasują do wyrażenia regularnego, co jest bardzo przydatne zarówno do ustalenia, co robi wyrażenie regularne, jak i do znalezienia tego, czego szukasz, kiedy to zrobisz. Domyślnie użytkownicy Ubuntu mają alias Bash, który powoduje grep --color=auto
uruchomienie - co jest wystarczające do tego celu - po uruchomieniu grep
z wiersza poleceń, więc prawdopodobnie nie musisz nawet --color
ręcznie przekazywać .
1 Dlatego .*
w wyrażeniu regularnym oznacza to, co *
oznacza w globu powłoki. Różnica polega jednak na tym, że grep
automatycznie drukuje wiersze zawierające dopasowanie w dowolnym miejscu , więc zazwyczaj nie ma potrzeby umieszczania .*
na początku lub na końcu wyrażenia regularnego.
* != any number of unknown characters