Mam plik, który ma „wtedy” i „tam”.
mogę
$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some
i ja mogę
$ grep "there " x.x
If there is no blob none some will be created
Jak mogę wyszukać oba w jednej operacji? próbowałem
$ grep (then|there) x.x
-bash: błąd składni w pobliżu nieoczekiwanego tokena `('
i
grep "(then|there)" x.x
durrantm.../code
# (Nothing)
grep
regular-expression
Michael Durrant
źródło
źródło
Odpowiedzi:
Musisz umieścić wyrażenie w cudzysłowie. Błąd, który otrzymujesz, jest wynikiem interpretacji bash
(
jako znaku specjalnego.Musisz także powiedzieć grepowi, aby używał rozszerzonych wyrażeń regularnych.
Bez rozszerzonych wyrażeń regularnych, trzeba uciec
|
,(
i)
. Pamiętaj, że używamy tutaj pojedynczych cudzysłowów. Bash specjalnie traktuje ukośniki odwrotne w obrębie podwójnych cudzysłowów.W tym przypadku grupowanie nie jest konieczne.
Byłoby to konieczne dla czegoś takiego:
źródło
grep $'then\nthere'
igrep -e then -e there
. Pamiętaj, że\|
nie jest to standardem w BRE. Reszta to. Bash traktuje backslashe specjalnie w cudzysłowach tylko przed"
,$
,\
,`
i nowej linii.x.x
?To tylko szybki dodatek, większość smaków ma polecenie o nazwie egrep, które jest po prostu grep z -E. Osobiście lubię pisać dużo lepiej
Niż użyć grep -E
źródło
Rzeczy udokumentowane w REGULARNE WYRAŻENIA na (lub przynajmniej mojej) stronie podręcznika są w rzeczywistości dla rozszerzonych wyrażeń regularnych;
Ale grep domyślnie ich nie używa - potrzebujesz
-E
przełącznika:Ponieważ (ponownie ze strony man):
Możesz więc użyć również:
Ponieważ w tym przypadku nawiasy są zbędne.
źródło
Wygląda na to, że elegancka prostota Basha gubi się na ogromnej stronie podręcznika.
Oprócz powyższych doskonałych rozwiązań, pomyślałem, że postaram się przedstawić wam ściągę na temat tego, jak bash analizuje i interpretuje wypowiedzi . Następnie, korzystając z tego przewodnika, przeanalizuję przykłady przedstawione przez pytającego, aby lepiej zrozumieć, dlaczego nie działają one zgodnie z przeznaczeniem.
Uwaga: Wiersze skryptu powłoki są używane bezpośrednio. Wpisane wiersze wprowadzania są najpierw rozszerzane w historii.
Każda linia uderzenia jest najpierw tokenizowana , czyli innymi słowy pocięta na tak zwane tokeny . (Tokenizacja występuje przed wszystkimi innymi rozszerzeniami, w tym nawiasami klamrowymi, tyldą, parametrem, poleceniem, arytmetyką, procesem, dzieleniem słów i rozwijaniem nazw plików).
Token tutaj oznacza część linii wejściowej oddzieloną (oddzieloną) jednym z tych specjalnych metaznaków:
Bash używa wielu innych znaków specjalnych, ale tylko te 10 produkuje początkowe żetony.
Ponieważ jednak te metaznaki również muszą być czasami używane w ramach tokena, musi istnieć sposób na usunięcie ich specjalnego znaczenia. To się nazywa ucieczka. Uciekając odbywa się albo poprzez cytowanie ciąg jednego lub więcej znaków (np
'xx..'
,"xx.."
) lub poprzedzając indywidualny charakter z back-slash (tj\x
). (Jest to trochę bardziej skomplikowane niż to, ponieważ cytaty również muszą być cytowane, a ponieważ podwójne cudzysłowy nie cytują wszystkiego, ale na razie wystarczy to uproszczenie).Nie myl cytowania bash z pomysłem cytowania ciągu tekstu, jak w innych językach. Pomiędzy cudzysłowami w bash nie są ciągi, lecz sekcje wiersza wejściowego, w których metaznaki są znakami ucieczki, aby nie ograniczały tokenów.
Zauważ, że istnieje ważna różnica między
'
, a"
, ale to na inny dzień.Pozostałe nieskalowane metaznaki stają się następnie separatorami tokenów.
Na przykład,
W pierwszym przykładzie są dwa tokeny wyprodukowane przez separator spacji:
echo
ixyz
.Podobnie w drugim przykładzie.
W trzecim przykładzie średnik jest uciekł, więc istnieją 4 żetony produkowane przez separator przestrzeni,
echo
,x;
,echo
, iy
. Pierwszy token jest następnie uruchamiany jako polecenie i przyjmuje kolejne trzy tokeny jako dane wejściowe. Uwaga: 2. miejsceecho
nie jest wykonywane.Ważną rzeczą do zapamiętania jest to, że bash najpierw szuka uciekających znaków (
'
,"
i\
), a następnie szuka nieskalowanych ograniczników meta-znaków, w tej kolejności.Jeśli nie uciekł, te 10 znaków specjalnych służy jako
token
ograniczniki. Niektóre z nich mają również dodatkowe znaczenie, ale przede wszystkim są ogranicznikami tokenów.Czego oczekuje grep
W powyższym przykładzie grep potrzebuje tych tokenów
grep
,string
,filename
.Pierwsza próba pytania brzmiała:
W tym przypadku
(
,)
i|
to bez zmiany znaczenia znaków meta i tak służyć do podziału wkładu w te tokeny:grep
,(
,then
,|
,there
,)
, ix.x
. grep chce zobaczyćgrep
,then|there
ix.x
.Drugą próbą pytania było:
Ten tokenizes w
grep
,(then|there)
,x.x
. Możesz to zobaczyć, jeśli zamienisz grep na echo:źródło