Я нашел несколько способов передать внешние переменные оболочки в awk
script, но я запутался в '
и "
.
Сначала я попробовал с оболочкой script:
$ 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
: (PS используйте пробел после -v
или он будет менее переносимым. Например, awk -v var=
not 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}'
Здесь мы получаем переменную после кода 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}"
Переменная также может быть добавлена в awk
используя здесь строку
awk '{print $0}' <<< "$variable"
test
Это так же, как:
echo "$variable" | awk '{print $0}'
PS, это угрожает переменной как входной файл
Когда вы пишете TrueY, вы можете использовать ENVIRON
для печати Environmental Variables
Установка переменной перед запуском AWK, вы можете распечатать ее так:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
Редактировать: Как пишет "тот другой парень", это не обрабатывает обратную косую черту. Не рекомендуется.
Как пишет Стивен Пенни, вы можете использовать ARGV
для передачи данных в awk.
v = "мои данные" awk 'BEGIN {print ARGV 1 }' "$ v" мои данные
Чтобы получить данные для самого кода, а не только для блока BEGIN, вам нужно уменьшить счетчик ARGV
с помощью ARGC--
v = "мои данные" эхо "тест" | awk 'BEGIN {ARGC--} {print ARGV 1, $ 0}' "$ v" мой тест данных
Вы можете использовать переменную в коде awk
, но она грязная и трудная для чтения, и, как указывает Charles Duffy
, эта версия также может стать жертвой внедрения кода. Если кто-то добавляет в переменную что-то плохое, он будет выполнен как часть кода awk
.
Это работает путем извлечения переменной в коде, поэтому она становится ее частью.
Если вы хотите создать awk
который динамически изменяется с использованием переменных, вы можете сделать это таким образом, бот НЕ используйте его для обычных переменных.
variable="line one\nline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
Вот пример внедрения кода:
variable='line one\nline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000
Вы можете добавить много команд в awk
таким образом. Даже сбой с недействительными командами.
Использование двойной кавычки
Всегда полезно заключить в кавычки переменную "$variable"
Если нет, несколько строк будут добавлены в виде одной длинной строки.
Пример:
var="Line one
This is line two"
echo $var
Line one This is line two
echo "$var"
Line one
This is line two
Другие ошибки, которые вы можете получить без двойной кавычки:
variable="line one\nline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: one\nline
awk: cmd. line:1: ^ syntax error
И с одинарной кавычкой, это не расширяет значение переменной:
awk -v var='$variable' 'BEGIN {print var}'
$variable
Фигурные скобки
Как пишет Johnsyweb, было бы неплохо использовать фигурную скобку для имени переменной, чтобы было понятно, как оно называется.
awk -v var='${variable}' 'BEGIN {print var}'
против
awk -v var='$variable' 'BEGIN {print var}'
Кажется, что старый добрый ENVIRON
awk встроенный хэш не упоминается вообще. Пример его использования:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
-v
не работает, если значение содержит обратную косую черту.
awk -vx='\c\d' ...
тогда он будет использован правильно. Но когда печатается x
awk удаляет знаменитое: awk: warning: escape sequence '\c' treated as plain 'c'
сообщение об ошибке awk: warning: escape sequence '\c' treated as plain 'c'
... Спасибо!
Использовать любой из них в зависимости от того, как вы хотите обратную косую черту в обрабатываемых переменных оболочки (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. Первый метод, приведенный выше, почти всегда является вашим лучшим вариантом и имеет самую очевидную семантику.
Вы можете передать параметр командной строки -v
с именем переменной (v
) и значением (=
) переменной окружения ("${v}"
):
% awk -vv="${v}" 'BEGIN { print v }'
123test
Или сделать его более понятным (с гораздо меньшим количеством v
):
% environment_variable=123test
% awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
123test
Вы можете использовать ARGV:
v=123test
awk 'BEGIN {print ARGV[1]}' "$v"
Обратите внимание, что если вы собираетесь продолжать работать в теле, вам нужно будет настроить ARGC:
awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
Я просто изменил @Jotne ответ для "for loop".
for i in 'seq 11 20'; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done
Мне пришлось вставлять дату в начале строк файла журнала, и она выполнялась, как показано ниже:
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log
Он может быть перенаправлен на другой файл для сохранения