Próbuję wydrukować linie za pomocą symbolu powtórzenia {n}, ale to nie działa. Dla. np. chcę wydrukować wszystkie linie o długości 4 znaków
awk '/^.{4}$/' test_data
Powyższy kod nie drukuje tego .Jak to naprawić, aby móc użyć symbolu powtórzenia? Znam alternatywę jak awk '/^....$/' test_data
iawk 'length ==3 ' test_data
awk
regular-expression
Forever Learner
źródło
źródło
awk '/^.{4}+$/{print}' <<<$'foods\nbaarsz\nfooo'
żeby dopasować dokładnie 4 znaki. Jak już wspomniałeś,awk 'length($0) == 4' test_data
jest kompatybilny z prawie wszystkimiawk
wersjami.awk --re-interval '/^.{4}$/' test_data
lubawk --posix '/^.{4}$/' test_data
pracy?Odpowiedzi:
Zgodnie z Podręcznikiem użytkownika GNU Awk: Historia funkcji , obsługa operatorów zakresu wyrażeń regularnych została dodana w wersji 3.0, ale początkowo wymagała jawnej opcji wiersza poleceń
Nowe opcje wiersza polecenia:
W
gawk
4.0Ponieważ używasz
gawk
3.x, będziesz musiał użyćlub
lub (dzięki @ StéphaneChazelas), jeśli chcesz mieć rozwiązanie przenośne, użyj
(ponieważ
--posix
lub--re-interval
spowodowałby błąd w innychawk
implementacjach).źródło
POSIXLY_CORRECT=anything awk '/^.{4}/'
ponieważ tworzy przenośny kod (a--posix
lub--re-interval
spowodowałby błąd w innychawk
implementacjach).ERE ( rozszerzone wyrażenia regularne używane przez
awk
lubegrep
) początkowo nie miały{x,y}
. Po raz pierwszy został wprowadzony w BRE (używanych przezgrep
lubsed
), ale ze\{x,y\}
składnią, która nie zepsuła przenośności wstecznej.Ale kiedy został dodany do ERE z tą
{x,y}
składnią, przerwał przenośność wsteczną, ponieważfoo{2}
RE dopasowywał wcześniej coś innego.Dlatego niektóre implementacje zdecydowały się tego nie robić. Znajdziesz to
/bin/awk
,/bin/nawk
a/bin/egrep
na Solarisie nadal nie honoruj tego (musisz użyć/usr/xpg4/bin/awk
lub/usr/xpg4/bin/grep -E
). Sama dlaawk
inawk
na FreeBSD (na podstawie utrzymane przez Brian Kernighana (The w )).awk
k
awk
W przypadku GNU
awk
do niedawna (wersja 4.0) trzeba było do niego zadzwonić,POSIXLY_CORRECT=anything awk '/^.{4}$/'
aby go uhonorować.mawk
wciąż tego nie szanuje .Zauważ, że ten operator to tylko cukier syntaktyczny.
.{3,5}
zawsze można napisać....?.?
na przykład (choć oczywiście{3,5}
jest o wiele bardziej czytelny, a odpowiednik(foo.{5,9}bar){123,456}
byłby o wiele gorszy).źródło
Działa to zgodnie z oczekiwaniami w przypadku GNU
awk
(gawk):Ale kończy się niepowodzeniem,
mawk
co jest bliższe POSIX,awk
a AFAIK jest ustawieniem domyślnym w systemach Ubuntu:Zatem prostym rozwiązaniem byłoby użycie
gawk
zamiastawk
.{n}
Notacja nie jest częścią składni POSIX BRE (podstawowe wyrażenie regularne). Dlategogrep
też tutaj zawodzi:Jest jednak częścią ERE (rozszerzone wyrażenia regularne):
Nie wiem, jakiego smaku wyrażenia regularnego używa. Używają starszej wersji ERE zgodnie z odpowiedzią Stéphane'a . W każdym razie albo najwyraźniej używasz wersjimawk
POSIXawk
, ale zgaduję, że to BREawk
, która nie implementuje ERE lub twoje dane wejściowe nie zawierają żadnych wierszy zawierających dokładnie 4 znaki. Może się to zdarzyć na przykład z powodu niewidocznych białych znaków lub glifów Unicode.źródło
length($0)
która jest bardziej wydajna niż wyrażenia regularne.mawk
nie jest tak naprawdę bliżej POSIXawk
i nie używa BRE. Używa ERE, ale bez{x,y}
operatora.