/ / AWK Dopasowywanie wzorców Regex - regex, awk

AWK Regex dopasowywanie wzorców - regex, awk

Mam plik tekstowy i muszę zidentyfikować pewien wzorzec w jednym polu. Używam AWK i próbuję użyć funkcji match ().

Wymagam, aby sprawdzić, czy poniższy wzór istnieje w ciągu cyfr

??????1?
??????3?
??????5?
??????7?

tzn. interesuje mnie tylko ostatnia, ale jedna cyfra to 1, 3, 5 lub 7.

Mam rozwiązanie, które wygląda tak;

    b = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]1[0-9]")
c = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]3[0-9]")
d = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]5[0-9]")
e = match($23, "[0-9][0-9][0-9][0-9][0-9][0-9]7[0-9]")

if (b || c || d || e)
{
print "Found a match" $23
}

Myślę, że chociaż powinienem umieć napisać tak zwięźle wyrażenie;

b = match($23, "[0-9]{6}1[0-9]")

ale to nie działa.

Czy brakuje mi czegoś lub są moje umiejętności w zakresie regresji (które nie są świetne), naprawdę tak źle?

z góry dziękuję

Odpowiedzi:

3 dla odpowiedzi № 1

Ogranicznik regex to /.../, nie "...". Kiedy używasz cudzysłowów w kontekście RE, jesteś "reinformując awk, że istnieje RE zapisany wewnątrz literału ciągu i ten tekst literowy zostanie sparsowany dwa razy, raz, gdy skrypt zostanie odczytany, a następnie ponownie, gdy zostanie wykonany, co sprawia, że ​​twoja specyfikacja RE jest o wiele bardziej skomplikowana, aby pomieścić to podwójne przetwarzanie.

Więc nie pisz:

b = match($23, "[0-9]{6}1[0-9]")

pisać:

b = match($23, /[0-9]{6}1[0-9]/)

zamiast.

Nie jest to jednak twój problem. Najprawdopodobniej masz problem z wywołaniem wersji awk, która nie obsługuje interwałów RE, takich jak {6}. Jeśli używasz starszej wersji awk GNU, możesz włączyć tę funkcję, dodając --re-interval flaga:

awk --re-interval "...b = match($23, /[0-9]{6}1[0-9]/)..."

ale czy to jest to, czy też używasz awk, który po prostu nie obsługuje RE_intervals, najlepszą rzeczą do zrobienia jest uzyskanie nowszej wersji gawk.

Na koniec cały skrypt można zredukować do:

awk --re-interval "$23 ~ /[0-9]{6}[1357][0-9]/{print "Found a match", $23}"

Zmiana [0-9] do [[:digit:]] dla niezależności od lokalizacji, jeśli chcesz.

Powodem, dla którego przedziały RE nie były domyślnie obsługiwane w gawk do niedawna, jest to, że stary awk nie obsługiwał ich, więc skrypt, który miał RE a{2}b gdy zostanie wykonany w starym awk, który by szukałdosłownie te 5 znaków i gawk nie chciały, aby stare skrypty cicho łamały się, gdy były wykonywane w gawk, zamiast w starym awk. Kilka zwolnień z powrotem gawk faceci słusznie zdecydowało się wziąć domyślnie włączone interwały RE dla naszej wygody w porównaniu z poprzednią zgodnością .


0 dla odpowiedzi nr 2

Tutaj jest jeden awk rozwiązanie:

awk -v FS="" "$7~/(1|3|5|7)/" file

Przez ustawienie FS do niczego, każda postać staje się polem. Możemy wtedy przetestować pole nr 7.

Jak pisał Tom.

awk -v FS="" "$7~/[1357]/" file