2016-09-08 14 views
6

że chce wyodrębnić podciągu, gdzie istnieje pewien wzór z rury oddzielone pliku tak, że stosuje się poniżej poleceniaJak dopasować wzorzec podany w zmiennej w awk?

awk -F ":" '/REWARD REQ. SERVER HEADERS/{print $1, $2, $3, $4}' sample_profile.txt 

Tutaj „NAGRODĄ REQ. SERVER HEADERS "to wzorzec, który ma być przeszukiwany w pliku i drukować pierwsze 4 części na linii oddzielonej dwukropkami.

Teraz chcę wysłać zmienną bash, aby działała jak wzorzec. w ten sposób użyłem pod komendą, ale to nie działa.

awk -v pat="$pattern" -F ":" '/pat/{print $1, $2 , $3, $4 } sample_profile.txt 

Jak mogę używać -v i -F w jednym poleceniu awk?

Odpowiedz

15

Problem tutaj nie ma nic wspólnego z -F.

Problem polega na użyciu /pat/, jeśli chcesz, aby zmienna była pat. Jeśli powiesz /pat/, , , rozumie to jako dosłowne "pat", więc spróbuje dopasować te linie zawierające ciąg "pat".

Jeśli chcesz podać wzór poprzez zmienną, trzeba użyć ~ jak to:

awk -v pat="$pattern" '$0 ~ pat' 

Wszystko razem, kod powinien być:

awk -v pat="$pattern" -F ":" '$0~pat{print $1, $2, $3, $4 }' file 
#        ^^^^^^ 

zobaczyć przykład:

Biorąc pod uwagę ten plik:

$ cat file 
hello 
this is a var 
hello bye 

Spójrzmy na linie zawierające "hello":

$ awk '/hello/' file 
hello 
hello bye 

Załóżmy teraz spróbuj poszukać dla "pat", zawartego w zmiennej, tak jak robiłeś to:

$ awk -v pat="hello" '/pat/' file 
$         # NO MATCHES! 

Załóżmy teraz użyć wyrażenia $0 ~ pat:

$ awk -v pat="hello" '$0~pat' file 
hello         # WE MATCH! 
hello bye 

Oczywiście można używać takich wyrażeń, aby dopasować tylko jedno pole i powiedzieć: awk -v pat="$pattern" '$2 ~ pat' file i tak dalej.

Od GNU Awk User's Guide → 3.1 How to Use Regular Expressions:

Kiedy regexp jest zamknięty w ukośniki, jak/foo /, nazywamy to wyrażenie regularne stałe, podobnie jak 5.27 jest stałą numeryczną i „foo” jest stałą łańcuchową.

I GNU Awk User's Guide → 3.6 Using Dynamic Regexps:

z prawej strony z „! ~” Operatora „~” lub nie musi być wyrażeniem regularnym stałej (tj, ciąg znaków między ukośnikami). Może to być dowolne wyrażenie . Wyrażenie jest obliczane i konwertowane na ciąg znaków, jeśli jest konieczne: ; zawartość ciągu jest następnie używana jako wyrażenie regularne. regexp obliczony w ten sposób nazywany jest dynamiczny regexp lub obliczane regexp:

BEGIN { digits_regexp = "[[:digit:]]+" } 
$0 ~ digits_regexp { print } 

Ustawia digits_regexp do regexp, który opisuje jeden lub więcej cyfr, i testów, czy rekord wejściowy pasuje do tego wyrażenia regularnego.

+1

dzięki za wskazanie, mój błąd i szczegółowo wyjaśnienia. –

4
awk -v pat="$pattern" -F":" '$0 ~ pat { print $1, $2, $3, $4 }' sample_profile.txt 

Nie można użyć zmiennej wewnątrz notacji regex // (nie ma sposobu, aby odróżnić ją od poszukiwania pat); musisz określić, że zmienna jest wyrażeniem regularnym z operatorem ~ (dopasowanie).

+0

To działa. Wielkie dzięki, uratowałeś moje godziny. –

0

To jest rodzaj hackowania, ale czyni mnie prostszym dla mnie.

cmd="awk '/$pattern/'" 
eval $cmd 

czyni go ciągiem pierwszy pozwala manipulować piłkę granicach awk