Awk — неограниченное регулярное выражение

Я пишу сценарий оболочки, который должен извлекать значения из текстового файла, который выглядит так:

app.full.name /warfilelocation/ warfilename

Мой сценарий оболочки будет перебирать список имен приложений и извлекать местоположение или имя с помощью AWK. Я проверил это в командной строке, используя следующее: awk "\$1 ~/app.full.name/ { print $2 }" application.txt

который возвращает то, что я ожидал, однако, когда я помещаю это в сценарий оболочки, у меня возникают проблемы.

У меня есть функция, которая выглядит так:

function get_location() {
        local application=$1
        awk "\$1 ~/^$application/ { print \$2 }"  applications.txt 
}

Но когда я вызываю эту функцию, я получаю следующую ошибку:

awk: $1 ~/^app.full.name
awk:      ^ unterminated regexp
awk: cmd. line:1: app.full.name
awk: cmd. line:1:         ^ syntax error
awk: cmd. line:2: app.full.name/ { print $2 }
awk: cmd. line:2:    ^ syntax error

У кого-нибудь есть идеи, что я делаю неправильно здесь. Я предполагаю, что я неправильно экранирую переменную, но независимо от того, что я пытаюсь, это не работает.

заранее спасибо


person BandyOrc    schedule 28.09.2011    source источник
comment
Как вы вызываете функцию? В чем ценность приложения?   -  person Matthew Farwell    schedule 28.09.2011


Ответы (4)


Используйте этот подход, чтобы заставить awk распознавать переменные оболочки:

awk -v "v1=$VAR1" -v "v2=$VAR2" '{print v1, v2}' input_file

Обновить

$ cat input
tinky-winky
dipsy
laa-laa
noo-noo
po

$ teletubby='po'

$ awk -v "regexp=$teletubby" '$0 ~ regexp' input
po

Обратите внимание, что в переменную оболочки может быть помещено что угодно, даже полноценное регулярное выражение, например ^d.*y. Просто убедитесь, что используете одинарные кавычки, чтобы оболочка не делала никаких расширений.

person Fredrik Pihl    schedule 28.09.2011
comment
он хочет заполнить значение переменной в Regex. не просто распечатать - person Kent; 28.09.2011
comment
@Kent - просто заявив, что -v позволяет вам использовать переменную оболочки в сценарии awk. Затем эту переменную можно использовать как регулярное выражение в функции match(); но эту часть я упустил... - person Fredrik Pihl; 28.09.2011
comment
я думаю, дело в совпадении(). поскольку переменная (by -v) не может использоваться в проверке соответствия awk, например ($x~/here/). по крайней мере, я не знаю, как использовать в этом случае. :) - person Kent; 28.09.2011
comment
@Kent - см. обновленный ответ, нет необходимости использовать функцию сопоставления - person Fredrik Pihl; 28.09.2011
comment
спасибо, я всегда боролся с двумя косыми чертами. :D здорово знать, как использовать переменную в регулярном выражении. +1 - person Kent; 28.09.2011

Сообщения об ошибках, кажется, указывают на то, что в конце $application есть случайная новая строка, которая дает сообщения об ошибках «строки 2».

person thiton    schedule 28.09.2011
comment
Это не то же самое, он хочет проверить первое поле, то есть $1 ~ /^app/ - person Matthew Farwell; 28.09.2011
comment
О, спасибо, не знал, что это настоящий синтаксис awk. Отредактировано. - person thiton; 28.09.2011

см. это: использование функции awk match()

kent$  app=app.ful
kent$  echo "app.full.name /warfilelocation/ warfilename"|awk -v a=$app '{if(match($1,a))print $2}' 
/warfilelocation/
person Kent    schedule 28.09.2011

Трудно сказать, не зная точно значения $application, но кажется, что у вас есть странный символ в $application, например, " или / или что-то в этом роде.

$ export application=foo/bar
$ awk "\$1 ~/^$application/ { print \$1 }"
gawk: cmd. line:1: $1 ~/^foo/bar/ { print $1 }
gawk: cmd. line:1:                ^ parse error

Я бы посмотрел на точное значение, которое у вас есть в $application, и если оно содержит /, экранируйте его.

Один из способов сделать это — использовать:

$ export application=`echo foo/bar | sed -e 's;/;\\\\/;g'`
$ awk "\$1 ~/^$application/ { print \$1 }"
person Matthew Farwell    schedule 28.09.2011