Jeśli grepuję dokument zawierający następujące elementy:
ThisExampleString
... dla wyrażenia This*String
lub *String
nic nie jest zwracane. Jednak This*
zwraca powyżej linii zgodnie z oczekiwaniami.
To, czy wyrażenie jest ujęte w cudzysłów, nie ma znaczenia.
Myślałem, że gwiazdka wskazuje dowolną liczbę nieznanych znaków? Dlaczego działa tylko wtedy, gdy jest na początku wyrażenia? Jeśli jest to zamierzone zachowanie, czego mam używać zamiast wyrażeń This*String
i *String
?
command-line
bash
grep
regex
Trae
źródło
źródło
* != any number of unknown characters
Odpowiedzi:
Gwiazdka w wyrażeniach regularnych oznacza „dopasuj poprzedni element 0 lub więcej razy”.
W twoim szczególnym przypadku z
grep 'This*String' file.txt
, próbujesz powiedzieć: „hej, grep, dopasuj do mnie słowoThi
, następnies
zero lub więcej małych liter , a następnie słowoString
”.s
Nigdzie nie ma małych literExample
, dlatego grep ignorujeThisExampleString
.W przypadku:
grep '*String' file.txt
mówisz „grep, dopasuj do mnie pusty ciąg - dosłownie nic - poprzedzający słowoString
”. Oczywiście nie takThisExampleString
należy to czytać. (Istnieją inne możliwe znaczenia - możesz wypróbować to z-E
flagą i bez niej - ale żadne z tych znaczeń nie jest podobne do tego, czego naprawdę chcesz tutaj.)Wiedząc, że
.
oznacza „dowolny pojedynczy znak”, możemy to zrobić:grep 'This.*String' file.txt
. Teraz polecenie grep odczyta go poprawnie:This
po nim następuje dowolny znak (pomyśl o nim jako o wyborze znaków ASCII) powtarzany dowolną liczbę razy, a następnieString
.źródło
*
jest znakiem specjalnym i należy go cytować lub uciec np. W ten sposób:grep 'This*String' file.txt
lub to:grep This\*String file.txt
aby nie być zaskoczonym nieoczekiwanymi wynikami.*
jest to symbol wieloznaczny. W grep*
jest operatorem wyrażeń regularnych. Zobacz unix.stackexchange.com/q/57957/70524strace grep .* file.txt |& head -n 1
istrace grep '.*' file.txt |& head -n 1
. W rzeczywistościgrep
działa również z dowolnymi znakami Unicode (np.echo -ne ⇏ | grep ⇏
Wyjściami⇏
)bash
. Oznacza to, że najpierwbash
interpretuje znaki specjalne i dopiero po wszystkich wykonanych rozszerzeniach przekazuje parametry do odrodzonego procesu. ----- Przykładowo tego polecenia Basha:grep This.\*String file.txt
będzie tarła/bin/grep
o tych parametrach: 0grep
, 1:This.*String
2:file.txt
. Zauważ, że Bash usunął odwrotny ukośnik, a pierwotny znak ucieczki*
został przekazany dosłownie.grep This.*String file.txt
zwykle będą działać, ponieważ najprawdopodobniej nie będzie pliku pasującego do wyrażenia wieloznacznego powłokiThis.*String
. W takim przypadku domyślnie Bash przekaże argument dosłownie obejmujący*
.*
Metaznak BRE 1 s, ERE 1 s i pcre 1 s mecze 0 lub więcej wystąpień wcześniej zgrupowanych wzoru (jeśli pogrupowane wzór poprzedzające*
metaznaku), 0 lub więcej wystąpień poprzedniego klasy postaci (jeśli klasa postaci jest poprzedzający*
metaznak) lub 0 lub więcej wystąpień poprzedniego znaku (jeśli*
metaznak nie występuje zgrupowany wzorzec ani klasa znaków );Oznacza to, że we
This*String
wzorcu, ponieważ*
metaznak nie jest poprzedzony ani zgrupowanym wzorcem, ani klasą znaków,*
metaznak pasuje do 0 lub więcej wystąpień poprzedniego znaku (w tym przypadkus
znak):Aby dopasować 0 lub więcej wystąpień dowolnego znaku, chcesz dopasować 0 lub więcej wystąpień
.
metaznaku, które pasują do dowolnego znaku:*
Metaznak w BRE oraz ERE jest zawsze „chciwy”, czyli będzie on pasował najdłuższy mecz:To może nie być pożądane zachowanie; w przeciwnym razie możesz włączyć
grep
silnik PCRE (korzystając z-P
opcji) i dołączyć?
metaznak, który po umieszczeniu po metaznakach*
i+
powoduje zmianę ich chciwości:1: Podstawowe wyrażenia regularne, rozszerzone wyrażenia regularne i wyrażenia regularne zgodne z Perl
źródło
Jednym z wyjaśnień znaleźć tutaj odwołuje się :
źródło
*
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 zmiangrep
. Chociaż rodzaj podobny koncepcyjnie, jakie*
środki do powłoki jest zupełnie inny od tego, co to znaczygrep
.Najpierw powłoka traktuje
*
jak symbol wieloznaczny.Powiedziałeś:
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 wykonaniemgrep
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 nieprzezroczystagrep
.) 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żnegoset -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
lubfailglob
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łownymb
,b*
zero lub więcejb
s, coab*c
odpowiadaac
,abc
,abbc
,abbbc
, itd.Podobnie, ponieważ
.
dopasowuje dowolny znak ,.*
zero lub więcej znaków 1 , coa.*c
meczówac
,akc
,ahjglhdfjkdlgjdfkshlgc
, nawetacccccchjckhcc
, itp OrKlasa postaci . Ponieważ
[xy]
meczex
luby
,[xy]*
dopasowuje zero lub więcej znaków, gdzie każdy z nich jest albox
alboy
, cop[xy]*q
pasujepq
,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. LubGrupy . Od
\(bar\)
meczówbar
,\(bar\)*
zero lub więcejbar
s, cofoo\(bar\)*baz
odpowiadafoobaz
,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óregrep
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: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 powodujegrep --color=auto
uruchomienie - co jest wystarczające do tego celu - po uruchomieniugrep
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, żegrep
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.źródło