Как использовать переменные оболочки в скрипте awk?
Я нашел несколько способов передать внешние переменные оболочки 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
Я запутался в этом.
10 ответов
Получение переменных оболочки в awk
может быть сделано несколькими способами. Некоторые лучше, чем другие.
Это лучший способ сделать это. Он использует -v
опция: (PS используйте пробел после -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,$0}' a="$var1" b="$var2" file
Переменная также может быть добавлена к 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
Редактировать: как "тот другой парень" пишет, это не обрабатывает обратную косую черту. Не рекомендуется.
Вы можете использовать переменную внутри 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 для деталей и других опций. Первый метод, описанный выше, почти всегда является вашим лучшим вариантом и имеет наиболее очевидную семантику.
Вы можете передать в опции командной строки -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], $0}' file "$v"
Я только что изменил ответ @Jotne на "для цикла".
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
Это можно перенаправить в другой файл, чтобы сохранить
пример:
in.txt:
Переменная:
var=$(awk '{print $1}' in.txt)
команда:
echo -e "$var" > out.txt
out.txt
Другая:
in.txt
foo,aaa
bar,bbb
Переменная:
var=$(awk -F "," '{print $1}' in.txt)
out.txt
foo
bar
или:
var=$(awk -F "," '{print $2}' in.txt)
out.txt
aaa
bbb
for i in chr{1..22} chrX chrY
do
awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
echo $i
done
Совет профессионала
Было бы удобно создать функцию, которая обрабатывает это, чтобы вам не приходилось каждый раз вводить все подряд. Используя выбранное решение, получаем ...
awk_switch_columns() {
cat < /dev/stdin | awk -v a="$1" -v b="$2" " { t = \$a; \$a = \$b; \$b = t; print; } "
}
И использовать его как ...
echo 'a b c d' | awk_switch_columns 2 4
Output:
a d c b