2009-07-01 9 views
40

Próbuję wyszukać podciągu „abc” w określonym pliku w linux/bashUżywanie znaku gwiazdy w grep

Więc robię:

grep '*abc*' myFile 

To nic nie zwraca.

Ale jeśli to zrobię:

grep 'abc' myFile 

Zwraca ona mecze poprawnie.

To nie jest dla mnie problem. Ale co, jeśli chcę grep do bardziej złożonego łańcucha, powiedzieć

*abc * def * 

Jak bym wykonać go za pomocą grep?

+3

grep sama robi” t obsługuje znaki wieloznaczne na większości platform. Musisz użyć egrep, aby użyć symboli wieloznacznych. Muszle mają inną składnię. "*" w powłoce to . W egrep jest operatorem, który mówi "0 do wielu poprzednich jednostek". W grep jest to zwykła postać. – PanCrit

+0

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

Odpowiedz

63

Gwiazdka to tylko repetition operator, ale musisz powiedzieć, co powtarzasz. /*abc*/ dopasowuje ciąg zawierający ab i zero lub więcej c (ponieważ drugi * jest na c, pierwszy jest bez znaczenia, ponieważ nie ma co go powtarzać). Jeśli chcesz cokolwiek dopasować, musisz powiedzieć .* - kropka oznacza dowolną postać (within certain guidelines). Jeśli chcesz tylko dopasować abc, możesz po prostu powiedzieć grep 'abc' myFile. Dla bardziej złożonego dopasowania musisz użyć .* - grep 'abc.*def' myFile dopasować ciąg znaków, który zawiera abc, a następnie def z czymś opcjonalnym pomiędzy.

Aktualizacja oparta na komentarz:

* w wyrażeniu regularnym nie jest dokładnie taka sama jak * w konsoli. W konsoli * jest częścią glob construct i działa jak symbol wieloznaczny (na przykład ls *.log wyświetli listę wszystkich plików, które kończą się .log). Jednak w wyrażeniach regularnych * jest modyfikatorem, co oznacza, że ​​dotyczy tylko poprzedzającej go postaci lub grupy. Jeśli chcesz, aby * w wyrażeniach regularnych działało jako symbol wieloznaczny, musisz użyć .* jak wcześniej wspomniano - kropka jest znakiem wieloznacznym, a gwiazda podczas modyfikowania kropki oznacza znalezienie jednej lub więcej kropek; to znaczy. znajdź jedną lub więcej dowolnych postaci.

+1

Myślę, że pytający jest zdezorientowany na temat różnicy między symbolami powłoki a wyrażeniami regularnymi. Podejrzewam również, że bardziej skomplikowanym wyrażeniem będzie: grep 'abc. * Def' (przynajmniej jedna z obecnych przestrzeni - być może dwie, jak pisałem). –

+1

W rzeczywistości, pytający zdaje się nie rozumieć, że "abc" to nie to samo co "^ abc $" :-D – Massa

+1

Tak, byłem zmieszany między globem a pełnymi wyrażeniami regularnymi. Używam * bez kropki do oznaczenia pasującego do niczego w powłoce. – Saobi

2

Spróbuj grep -E dla rozszerzonego obsługę wyrażeń regularnych

wziąć również zapoznać się na stronie:

The grep man page

8

„gwiazda znak” ma sens tylko wtedy, jeśli coś jest przed nim. Jeśli nie ma narzędzia (grep w tym przypadku) może po prostu potraktować to jako błąd. Na przykład:

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

* nie jest bez znaczenia; po prostu nie ma zwykłego znaczenia (powtórzenia), ale oznacza "Jestem gwiazdą". Pasowałaby do linii zawierającej gwiazdę, po której następują x, yi z. –

+1

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

0

„*” działa jako modyfikator do poprzedniej pozycji. Tak więc "abc * def" wyszukuje "ab", po którym następuje 0 lub więcej "c" po "def".

Najprawdopodobniej jest to "abc. * Def", który wyszukuje "abc", a następnie dowolną liczbę znaków, po których następuje "def".

7

Znak kropki oznacza pasujący do dowolnego znaku, więc ". *" Oznacza zero lub więcej wystąpień dowolnego znaku. Prawdopodobnie chcesz użyć ". *" Zamiast "*".

Ach, gówno,

1

Użyj grep -P - który umożliwia obsługę wyrażeń regularnych stylu Perl.

grep -P "abc.*def" myfile 
4

Wyrażenie próbowałeś, jak te, które działają w wierszu poleceń powłoki w Linux na przykład, jest nazywany „glob”. Wyrażenia globu nie są pełne regular expressions, czyli to, czego używa grep do określenia ciągów do wyszukania. Here to (stary, mały) post o różnicach. Wyrażenia globalne (jak w "ls *") są interpretowane przez samą powłokę.

Możliwe jest przetłumaczenie z globów na REs, ale zwykle musisz to zrobić w swojej głowie.

+1

To tylko glob, jeśli jest parsowany przez powłokę. Ponieważ zachowuje ciąg wyszukiwania wewnątrz pojedynczych cudzysłowów, powłoka pozostawia ciąg znaków samodzielnie i przekazuje go w stanie nienaruszonym w argv do grep. –

4

Nie używasz wyrażeń regularnych, więc twój wariant grep powinien być fgrep, który będzie się zachowywać zgodnie z oczekiwaniami.

0

To może być odpowiedź szukasz:

grep abc MyFile | grep def 

Jedyną rzeczą jest to, że będzie ... linie wyjściowe były „def” jest przed lub po „abc”