Как Крис говорит , аргументы формы variablename=anything
рассматриваются как присвоение переменной (, которое выполняется во время обработки аргументов, в отличие от (более новых)-v var=value
которые выполняются перед операторами BEGIN
)вместо имен входных файлов.
Это может быть полезно в таких случаях, как:
awk '{print $1}' FS=/ RS='\n' file1 FS='\n' RS= file2
Где вы можете указать различные FS
/ RS
для каждого файла. Он также широко используется в:
awk '!file1_processed{a[$0]; next}; {...}' file1 file1_processed=1 file2
Какая версия более безопасна:
awk 'NR==FNR{a[$0]; next}; {...}' file1 file2
(который не работает, если file1
пусто)
Но это мешает, когда у вас есть файлы, имя которых содержит =
символов.
Теперь это проблема только тогда, когда то, что осталось от первого =
, является действительным awk
именем переменной.
То, что составляет допустимое имя переменной в awk
, более строго, чем в sh
.
POSIX требует, чтобы это было что-то вроде:
[_a-zA-Z][_a-zA-Z0-9]*
Только с символами переносимого набора символов. Однако /usr/xpg4/bin/awk
Solaris 11, по крайней мере, не соответствует требованиям в этом отношении и допускает использование любых буквенных символов в локали в именах переменных, а не только -zA -Z.
Таким образом, аргумент типа x+y=foo
, =bar
или ./foo=bar
по-прежнему обрабатывается как имя входного файла, а не как присваивание, поскольку то, что осталось от первого =
, не является допустимым именем переменной. Такой аргумент, как Stéphane=Chazelas.txt
, может быть, а может и не быть, в зависимости от реализации awk
и локали.
Вот почему с awk рекомендуется использовать:
awk '...'./*.txt
вместо
awk '...' *.txt
, например, чтобы избежать проблемы, если вы не можете гарантировать, что имя файлов txt
не будет содержать символы =
.
Кроме того, имейте в виду, что такой аргумент, как -vfoo=bar.txt
, может рассматриваться как вариант, если вы используете:
awk -f file.awk -vfoo=bar.txt
(также относится к awk '{code}' -vfoo=bar.txt
с awk
из busybox версий до 1.28.0, см. соответствующий отчет об ошибке).
Опять же,использование ./*.txt
работает вокруг этого (использование префикса ./
также помогает с файлом с именем -
, который в противном случае awk
понимается как значение стандартный ввод вместо ).
Вот почему
#! /usr/bin/awk -f
Шебанги на самом деле не работают. В то время как var=value
можно обойти, исправив , значения ARGV
(добавляют префикс ./
)в операторе BEGIN
:
.
#! /usr/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++)
if (ARGV[i] ~ /^[_[:alpha:]][_[:alnum:]]*=/)
ARGV[i] = "./" ARGV[i]
}
# rest of awk script
Это не поможет с опциями, так как их видит скрипт awk
, а не скрипт awk
.
Одна потенциальная косметическая проблема с использованием этого префикса ./
заключается в том, что он заканчивается в FILENAME
, но вы всегда можете использовать substr(FILENAME, 3)
, чтобы удалить его, если он вам не нужен.
Реализация GNU awk
устраняет все эти проблемы с помощью опции -E
.
После -E
gawk ожидает только путь awk
скрипта (, где -
по-прежнему означает stdin ), а затем только список путей к входным файлам (, а там даже не -
обрабатывается особым образом ).
Специально разработан для:
#! /usr/bin/gawk -E
shebangs, где список аргументов всегда является входными файлами (обратите внимание, что вы по-прежнему можете редактировать этот ARGV
список в операторе BEGIN
).
Вы также можете использовать его как:
gawk -e '...awk code here...' -E /dev/null *.txt
Мы используем -E
с пустым скриптом (/dev/null
), чтобы гарантировать, что эти *.txt
последующие файлы всегда обрабатываются как входные файлы, даже если они содержат символы =
.
Задан вопрос вверх по течению , после ответа он будет опубликован здесь.
Редактировать :это возможно, но с не -пользователем root. Это привело к обновлениям документации .