Odpowiedzi:
Szukasz niechcianego (lub leniwego) meczu. Aby uzyskać niechciane dopasowanie w wyrażeniach regularnych, musisz użyć modyfikatora ?
po kwantyfikatorze. Na przykład możesz zmienić .*
na .*?
.
Domyślnie grep
nie obsługuje niechcianych modyfikatorów, ale możesz użyć grep -P
składni Perla.
.
dopasować znaki nowej linii, nazywa się DOTALL lub trybem jednowierszowym ; Ruby jest jedynym, który nazywa to multilinią . W innych wariantach multiline to tryb, który pozwala kotwicom ( ^
i $
) dopasować się na granicach linii. Ruby nie ma równoważnego trybu, ponieważ w Rubim zawsze działa w ten sposób.
-P
był dla mnie zupełnie nowy, szczęśliwie uciekam od lat i wykorzystuję tylko -E
... tak wiele zmarnowanych lat! - Notatka dla siebie: czytaj ponownie strony podręcznika jako (nawet bardziej!) Normalną czynność, nigdy nie przyswajasz wystarczającej liczby przełączników i opcji.
grep
nie obsługuje -P
, ale jeśli używasz egrep
, możesz użyć .*?
wzorca, aby osiągnąć ten sam efekt. egrep -o 'start.*?end' text.html
-P
ale -E
wywołuje, egrep
dlatego sugerowane .*?
działa dobrze.
Właściwie .*?
jedyny działa w perl
. Nie jestem pewien, jaka byłaby równoważna składnia rozszerzonych wyrażeń regularnych grep. Na szczęście możesz użyć składni perl z grep, więc grep -P
zadziała, ale grep -E
która jest taka sama, jak egrep
nie zadziała (byłby chciwy).
Zobacz też: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html
grep -P
nie działa w GNU grep 2.9 - tylko próbował go (nie robi błędów, tak cicho nie stosować ?
Intertestly nie robi. nie klasy np:env|grep '[^\=]*\='
grep -P
opcji ani pgrep
polecenia, ale egrep
działa świetnie.
pgrep
moim pudełku z OS X 10.9 jest polecenie, ale jest to zupełnie inny program, którego celem jest „znajdowanie lub sygnalizowanie procesów według nazwy”.
Mój grep, który działa po wypróbowaniu rzeczy w tym wątku:
echo "hi how are you " | grep -shoP ".*? "
Tylko pamiętaj, aby dodać spację do każdego wiersza
(Mój był wiersz po wierszu wyszukiwania, aby wypluć słowa)
-shoP
fajny mnemonik :)
echo "bbbbb" | grep -shoP 'b.*?b'
to trochę pouczające doświadczenie. Jedyna rzecz, która zadziałała dla mnie również w kategoriach wyraźnego lenistwa.
grep
Aby nie być chciwym, grep
możesz użyć zanegowanej klasy znaków. Innymi słowy, staraj się unikać symboli wieloznacznych.
Na przykład, aby pobrać wszystkie linki do plików jpeg z zawartości strony, użyjesz:
grep -o '"[^" ]\+.jpg"'
Aby poradzić sobie z wieloma liniami, xargs
najpierw przepuść wejście . Aby uzyskać wydajność, użyj ripgrep
.
Krótka odpowiedź to użycie następnego wyrażenia regularnego:
(?s)<car .*? model=BMW .*?>.*?</car>
(Nieco) bardziej skomplikowana odpowiedź brzmi:
(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>
Umożliwi to dopasowanie car1 i car2 w poniższym tekście
<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
Przepraszam, że spóźniłem się 9 lat, ale może to zadziałać dla widzów w 2020 roku.
Załóżmy więc, że masz taką linię "Hello my name is Jello"
. Teraz chcesz znaleźć słowa, które zaczynają się 'H'
i kończą na 'o'
, z dowolną liczbą znaków pomiędzy nimi. I nie chcemy wersetów, chcemy tylko słów. W tym celu możemy użyć wyrażenia:
grep "H[^ ]*o" file
To zwróci wszystkie słowa. Sposób, w jaki to działa, jest następujący: Pozwoli to na wszystkie znaki zamiast spacji pomiędzy, w ten sposób możemy uniknąć wielu słów w tej samej linii.
Teraz możesz zastąpić spację dowolnym innym znakiem. Załóżmy, że początkowy wiersz brzmiał "Hello-my-name-is-Jello"
, wtedy możesz uzyskać słowa za pomocą wyrażenia:
grep "H[^-]*o" file
Wiem, że to trochę martwy punkt, ale właśnie zauważyłem, że to działa. Usunięto zarówno czyszczenie, jak i porządkowanie z mojego wyniku.
> grep -v -e 'clean\-\?up'
> grep --version grep (GNU grep) 2.20