Как да използвам променливи на обвивката в awk скрипт?

Намерих няколко начина за предаване на външни променливи на shell към скрипт awk, но съм объркан относно ' и ".

Първо опитах с шел скрипт:

$ v=123test
$ echo $v
123test
$ echo "$v"
123test

След това опитах с awk:

$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123

Защо е разликата?

Накрая опитах това:

$ awk 'BEGIN{print " '$v' "}'
$  123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1:             ^ unexpected newline or end of string 

Объркан съм от това.

Решение

Получаване на променливи на обвивката в awk

може да се извърши по няколко начина. Някои от тях са по-добри от други. Това трябва да покрие повечето от тях. Ако имате коментар, моля, оставете го по-долу.


Използване на -v (Най-добрият начин, най-преносимият)

Използвайте опцията -v: (P.S. Използвайте интервал след -v, иначе ще бъде по-малко преносимо. Например, awk -v var=, а не awk -vvar=)

variable="line one\nline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two

Това би трябвало да е съвместимо с повечето awk, а променливата е достъпна и в блока BEGIN:

Ако имате няколко променливи:

awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'

Предупреждение. Както пише Ед Мортън, ескейп последователностите ще бъдат интерпретирани, така че \t ще се превърне в истински tab, а не \t, ако това е, което търсите. Може да се реши с помощта на ENVIRON[] или да се получи достъп чрез ARGV[]

PS Ако искате да използвате три вертикални чертички като разделител ||||, те не могат да бъдат избягнати, затова използвайте -F"[|][|][|][|]"

Пример за получаване на данни от програма/функция inn to awk (тук се използва дата)

awk -v time="$(date +"%F %H:%M" -d '-1 minute')" 'BEGIN {print time}'

Променлива след блока с код

Тук получаваме променливата след кода awk. Това ще работи добре, стига да не се нуждаете от променливата в блока BEGIN:

variable="line one\nline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file

Това работи и с множество променливи awk '{print a,b,$0}' a="$var1" b="$var2" file

Използването на променлива по този начин не работи в блок BEGIN:

echo "input data" | awk 'BEGIN {print var}' var="${variable}"

Here-string

Променливата може да бъде добавена към awk и с помощта на [here-string][1] от шеловете, които ги поддържат (включително Bash):


awk '{print $0}' 
Коментари (6)

Използвайте някоя от тях в зависимост от това как искате да се обработват обратните наклонени черти в променливите на обвивката (avar е променлива на awk, svar е променлива на обвивката):

awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file

Вижте http://cfajohnson.com/shell/cus-faq-2.html#Q24 за подробности и други опции. Първият метод по-горе почти винаги е най-добрият вариант и има най-очевидна семантика.

Коментари (0)

Можете да подадете опцията на командния ред -v с име на променлива (v) и стойност (=) на променливата на средата ("${v}"):

% awk -vv="${v}" 'BEGIN { print v }'
123test

Или, за да стане по-ясно (с много по-малко v):

% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
Коментари (0)