Dlaczego `grep fil *` zawodzi?

9

Znalazłem, że się echo file|grep fil*nie udaje, ale się echo abcd|grep abc*udaje.

Nie rozumiem tego, czy ktoś może wyjaśnić?

tmpbin
źródło
Czy możesz dodać system i wersję grep? Dzieje się tak, ponieważ w przypadku gnugrep 2.16 (pod Ubuntu 14.04 LTS) nie generuje żadnego błędu (kod wyjścia 0) i dopasowuje trzy pierwsze litery. Na przykład echo file|grep fil*odpowiedzi file.
Hastur
3
@Hastur Problem jest spowodowany rozszerzeniem nazwy pliku przed wyrażeniem regularnym. Mój katalog roboczy zawiera plik z prefiksem pliku fil, ale nie plik z prefiksem abc, więc fil * jest zastąpiony nazwą pliku, ale abc * pozostaje niezmieniony.
tmpbin
Dzięki, nie myślałem o tym. Kiedy podejmuję próby, wypróbowuję je w nowym katalogu ...
Hastur

Odpowiedzi:

31

Istnieją dwa problemy z twoim przykładem.

Po pierwsze, zakładasz, że wyrażenia regularne działają tak samo jak wzorce globu, ponieważ *jest to symbol wieloznaczny oznaczający „dowolną sekwencję znaków”. W wyrażeniach regularnych *oznacza zamiast tego „dowolną liczbę poprzedniego atomu”, a więc fil*oznacza, fpo którym inastępuje zero lub więcej lznaków. Musisz powiedzieć, grep fil.*aby uzyskać zamierzone znaczenie: .oznacza „dowolny pojedynczy znak, co .*oznacza„ dowolną sekwencję znaków ”.

Mniejszy problem polega na tym, że używasz niecytowanych znaków specjalnych, które oznaczają coś według reguł globalnych, co oznacza, że ​​powłoka może je interpretować. Jeśli masz w katalogu lokalnym jakieś pliki pasujące do wzorców globu fil*lub abc*, powłoka je rozszerzy , więc grepotrzyma rozwinięte nazwy plików jako wzorzec, a nie zamierzoną RE. Kiedykolwiek używasz takich znaków w wierszu poleceń, należy je zacytować: echo file | grep 'fil.*'.

Warren Young
źródło