Używanie znaku gwiazdki w grep


88

Próbuję wyszukać podłańcuch „abc” w określonym pliku w linux / bash

Ja również:

grep '*abc*' myFile

Nic nie zwraca.

Ale jeśli to zrobię:

grep 'abc' myFile

Zwraca poprawnie dopasowania.

Teraz to nie jest dla mnie problem. Ale co, jeśli chcę grepować dla bardziej złożonego ciągu, powiedzmy

*abc * def *

Jak mógłbym to osiągnąć używając grep?


3
Sam grep nie obsługuje symboli wieloznacznych na większości platform. Aby używać symboli wieloznacznych, musisz użyć egrep. Pociski mają inną składnię. „*” w powłoce to <dowolny ciąg znaków>. W egrep jest to operator, który mówi „0 do wielu poprzednich jednostek”. W grep jest to zwykła postać.
PanCrit

@PanCrit: *oznacza to samo w grep i egrep: jest to kwantyfikator oznaczający zero lub więcej poprzedzającego atomu. To zupełnie inna koncepcja niż symbole wieloznaczne używane przez powłokę.
Alan Moore

Odpowiedzi:


123

Gwiazdka to tylko operator powtórzenia , ale musisz powiedzieć, co powtarzasz. /*abc*/dopasowuje ciąg zawierający ab i zero lub więcej c (ponieważ druga * znajduje się na c; pierwsza jest bez znaczenia, ponieważ nie ma nic do powtórzenia). Jeśli chcesz coś dopasować, musisz powiedzieć .*- kropka oznacza dowolny znak ( w określonych wytycznych ). Jeśli chcesz po prostu dopasować abc, możesz po prostu powiedzieć grep 'abc' myFile. Aby uzyskać bardziej złożone dopasowanie, musisz użyć .*- grep 'abc.*def' myFiledopasuje ciąg zawierający abc, po którym następuje def, z czymś opcjonalnie pomiędzy.

Aktualizacja na podstawie komentarza:

*w wyrażeniu regularnym nie jest dokładnie tym samym, co * w konsoli. W konsoli * jest częścią konstrukcji glob i działa tylko jako symbol wieloznaczny (na przykład ls *.logwyświetla listę wszystkich plików kończących się na .log). Jednak w wyrażeniach regularnych * jest modyfikatorem, co oznacza, że ​​ma zastosowanie tylko do poprzedzającego go znaku lub grupy. Jeśli chcesz, aby * w wyrażeniach regularnych działał jak symbol wieloznaczny, musisz użyć tego, .*jak wspomniano wcześniej - kropka jest symbolem wieloznacznym, a gwiazdka podczas modyfikowania kropki oznacza znalezienie jednej lub więcej kropek; to znaczy. znajdź jedną lub więcej dowolnych postaci.


1
Myślę, że osoba pytająca jest zdezorientowana różnicą między symbolami wieloznacznymi powłoki a wyrażeniami regularnymi. Podejrzewam również, że bardziej skomplikowanym wyrażeniem byłoby: grep 'abc. * Def' (przynajmniej jedna spacja - prawdopodobnie dwie, jak napisałem).
Jonathan Leffler

1
W rzeczywistości osoba pytająca wydaje się nie rozumieć, że „abc” to nie to samo, co „^ abc $” :-D
Massa

1
Tak, pomyliłem się między globem a pełnymi wyrażeniami regularnymi. Używam * bez kropki, aby oznaczać dopasowanie czegokolwiek na powłoce.
Saobi

1
grep *oznacza „0 lub więcej”, a grep jest domyślnie chciwy. Należy zauważyć, że w grep podstawowych wyrażeniach regularnych metaznaki ?, +, {, |, (, i )tracą swoje szczególne znaczenie. Więcej informacji:
wyrażenia

25

Znak kropki oznacza dopasowanie dowolnego znaku, więc .*oznacza zero lub więcej wystąpień dowolnego znaku. Prawdopodobnie masz na myśli .*raczej używanie niż tylko *.


Kropka to meta znak, który akceptuje dowolny znak z wyjątkiem nowych linii .
Abhishek Kamal

12

„Znak zodiaku” ma znaczenie tylko wtedy, gdy coś się przed nim znajduje. Jeśli nie ma narzędzia (w tym przypadku grep), może to potraktować jako błąd. Na przykład:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

5
* Nie jest bez znaczenia; po prostu nie ma swojego zwykłego znaczenia (powtórzenia), ale oznacza „jestem gwiazdą”. Dopasowałaby linię zawierającą gwiazdkę, po której następuje x, y i z.
Jonathan Leffler

2
@Jonathan To zależy od narzędzia.


6

Wyrażenie, które wypróbowałeś, podobnie jak te, które działają w wierszu poleceń powłoki na przykład w Linuksie, nazywa się „ glob ”. Wyrażenia glob nie są pełnymi wyrażeniami regularnymi , których używa grep do określania ciągów znaków, które mają być wyszukiwane. Oto (stary, mały) post o różnicach. Wyrażenia glob (jak w „ls *”) są interpretowane przez samą powłokę.

Możliwe jest tłumaczenie z globów na RE, ale zazwyczaj musisz to zrobić w głowie.


1
To tylko glob, jeśli jest analizowany przez powłokę. Ponieważ zachowuje on szukany ciąg w pojedynczych cudzysłowach, powłoka zostawia ten ciąg w spokoju i przekazuje go w stanie nienaruszonym w argv do grep.
Conspicuous Compiler

4

Nie używasz wyrażeń regularnych, więc Twój wybrany wariant grep powinien być taki fgrep, który będzie zachowywał się tak, jak tego oczekujesz.


2
fgrepjest obecnie przestarzała, grep -fnależy jej używać.
Prometheus

1
To jest „grep -F”. Stary dobry fgrep może być „przestarzały”, ale nie zamierzają go odebrać, póki jeszcze żyję.
Andrew Beals,


1

To może być odpowiedź, której szukasz:

grep abc MyFile | grep def

Chodzi tylko o to, że ... wyświetli wiersze, w których "def" jest przed OR po "abc"


1

To zadziałało dla mnie:

grep ". * $ {wyrażenie}" - w cudzysłowach poprzedzonych kropką. Gdzie „wyrażenie” to dowolny ciąg, którego potrzebujesz na końcu linii.

Standardowy unix grep bez dodatkowych przełączników.


0

„*” działa jako modyfikator dla poprzedniego elementu. Zatem „abc * def” wyszukuje „ab”, po którym następuje 0 lub więcej „c”, a następnie „def”.

To, czego prawdopodobnie potrzebujesz, to „abc. * Def”, które wyszukuje „abc”, po którym następuje dowolna liczba znaków, a następnie „def”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.