Chcę wykonać niepochodny wzór (wyrażenie regularne) awk
. Oto przykład:
echo "@article{gjn, Author = {Grzegorz J. Nalepa}, " | awk '{ sub(/@.*,/,""); print }'
Czy można napisać wyrażenie regularne, które wybiera krótszy ciąg?
@article{gjn,
zamiast tego długiego łańcucha ?:
@article{gjn, Author = {Grzegorz J. Nalepa},
Chcę uzyskać ten wynik:
Author = {Grzegorz J. Nalepa},
Mam inny przykład:
echo ” , artykuł {gjn, Autor = {Grzegorz J. Nalepa}," | awk '{sub (/ , [^,] *, /, ""); drukuj} ↑ ↑ ^^^^^
Zauważ, że zmieniłem @
znaki na przecinek ( ,
) na pierwszej pozycji zarówno ciągu wejściowego, jak i wyrażenia regularnego (a także zmieniłem .*
na [^,]*
). Czy można napisać wyrażenie regularne, które wybiera krótszy ciąg?
, Author = {Grzegorz J. Nalepa},
zamiast dłuższego ciągu ?:
,article{gjn, Author = {Grzegorz J. Nalepa},
Chcę uzyskać ten wynik:
,article{gjn
awk
regular-expression
nowy1
źródło
źródło
Author
przecinka i białych znaków, a następnie białych znaków, a=
następnie białych znaków, a{
następnie dowolnych znaków, po których nie}
następuje}
, chociaż wymaga to (między innymi), że nie można zagnieździć{}
wewnątrz tej= { ... }
części.Odpowiedzi:
Jeśli chcesz wybrać,
@
a później do pierwszego,
, musisz określić jako@[^,]*,
To jest
@
następuje dowolny numer (*
) bezczynności przecinkami ([^,]
) przecinek (,
).Takie podejście działa jak ekwiwalent
@.*?,
, ale nie w przypadku takich rzeczy@.*?string
, w których to, co jest później, to więcej niż jedna postać. Negowanie postaci jest łatwe, ale negowanie ciągów wyrażeń regularnych jest o wiele trudniejsze .Innym podejściem jest wstępne przetworzenie danych wejściowych w celu zastąpienia lub uzupełnienia
string
znakiem, który inaczej nie występuje w danych wejściowych:Jeśli nie możesz zagwarantować, że dane wejściowe nie będą zawierać twojego zamiennego znaku (
\1
powyżej), jednym z podejść jest użycie mechanizmu zmiany znaczenia:Działa to dla stałych
string
s, ale nie dla dowolnych wyrażeń regularnych, jak dla odpowiednika@.*?foo.bar
.źródło
Istnieje już kilka dobrych odpowiedzi zapewniających obejście problemu
awk
niezdolności do wykonywania chciwych dopasowań, dlatego podaję informacje o alternatywnym sposobie zrobienia tego przy użyciu wyrażeń regularnych zgodnych z Perl (PCRE). Zauważ, że najprostszeawk
skrypty „dopasuj i wydrukuj” można łatwo zaimplementować ponownieperl
za pomocą opcji-n
wiersza poleceń, a bardziej złożone skrypty można przekonwertować za pomocą awk a2p na translator Perl.Perl ma niewdzięczny operator, którego można używać w skryptach Perla i we wszystkim, co korzysta z PCRE. Na przykład, również zaimplementowany w opcji GNU grep
-P
.PCRE nie jest identyczny z wyrażeniami regularnymi Perla, ale jest bardzo blisko. Jest to popularny wybór biblioteki wyrażeń regularnych dla wielu programów, ponieważ jest bardzo szybki, a rozszerzenia Perla do rozszerzonych wyrażeń regularnych są bardzo przydatne.
Ze strony podręcznika perlre (1) :
źródło
To jest stary post, ale poniższe informacje mogą być przydatne dla innych.
Istnieje sposób, co prawda prymitywne, na wykonanie niechcianego dopasowania RE w awk. Podstawową ideą jest użycie funkcji dopasowania (ciąg, RE) i stopniowe zmniejszanie rozmiaru ciągu, aż dopasowanie się nie powiedzie, coś w stylu (nieprzetestowane):
źródło
W przypadku wyrażeń ogólnych można tego użyć jako niepochodnego dopasowania:
Używam tego na podstawie odpowiedzi @ JimMellander.
smatch
zachowuje się jakmatch
, zwracając:źródło
W awk nie ma sposobu na dopasowanie bez chciwości. Możesz jednak uzyskać pożądaną moc wyjściową. sugestia sch będzie działać dla tej linii. Jeśli nie możesz polegać na przecinku, ale „Autor” jest zawsze początkiem tego, czego chcesz, możesz to zrobić:
Jeśli liczba znaków poprzedzających autora jest zawsze taka sama, możesz to zrobić:
Musisz tylko wiedzieć, jak wyglądają Twoje dane w całym zestawie.
źródło
Zawsze jest rozwiązanie. Dany problem można rozwiązać dość łatwo, używając przecinków jako separatora.
Kiedy liczba pól jest różna, zwykle potrzebne jest coś nieco lepszego. W takim przypadku znalezienie słów stop często się opłaca, ponieważ można wyciąć wszystko z linii, używając ich. W kontekście tego przykładu rozumiem słowa stop.
źródło
Wiem, że to stary post. Ale tutaj jest coś, co używa awk jako OP zgodnie z żądaniem:
A = @ artykuł {gjn2010jucs, Autor = {Grzegorz J. Nalepa},
echo $ A | awk 'sub (/ @ [^,] * /, "")'
Wyjście:,
Autor = {Grzegorz J. Nalepa},
źródło