Как использовать переменные оболочки в сценарии awk?
Я нашел несколько способов передать внешние переменные оболочки к awk
скрипт, но я запутался в '
и "
.
во-первых, я попытался с shell-скрипт:
$ 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
Я в замешательстве.
8 ответов
получение переменных оболочки в awk
может быть сделано несколькими способами. Некоторые лучше других.
это лучший способ сделать это. Он использует : (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}'
здесь мы получаем переменную после 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,}' a="$var1" b="$var2" file
переменная также может быть добавлена в awk
используя вот строка
awk '{print }' <<< "$variable"
test
это то же, что:
echo "$variable" | awk '{print }'
PS, это угрожает переменной как файл ввод
как TrueY написать, вы можете использовать ENVIRON
печати Environmental Variables
Установка переменной перед запуском AWK вы можете распечатать ее следующим образом:
X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash
Edit: как пишет "тот другой парень", это не обрабатывает обратную косую черту. Не рекомендуемый.
вы можете использовать переменную внутри 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
Кажется, что старый-добрый ENVIRON
awk встроенный хэш не упоминается вообще. Пример его использования:
$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt
используйте любой из них в зависимости от того, как вы хотите, чтобы обратные косые черты в переменных оболочки обрабатывались (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
s):
% 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], }' file "$v"
мне пришлось вставить дату в начале строки лог-файла, и это сделано, как показано ниже:
DATE=$(date +"%Y-%m-%d")
awk '{ print "'"$DATE"'", ; }' /path_to_log_file/log_file.log
его можно перенаправить в другой файл, чтобы сохранить
Я только что изменил ответ @Jotne на "for loop".
for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " }'; done
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done