Есть ли 2 способа установить awk vars через командную строку?


10

Я заметил пример O'Reilly awk(1997), который назначал переменную awk, устанавливая ее в командной строке после текста программы. Это работает, но я не могу найти этот синтаксис в man / info awk . Я только что пропустил это; это ограничено ...? Единственный синтаксис, который я видел в руководстве - это -vопция.

awk '/home/{print foo, bar}' foo="cat" bar="dog" /proc/$$/cmdline

Вывод: cat dog

Ответы:


11

Это на самом деле в POSIX awk(ссылка на POSIX 2008, предыдущие версии тоже были, я считаю). -vописано в разделе « Параметры », другой способ - в разделе « Операнды ».

Существует разница между -vпередачей назначений в конце с именами файлов:

  • С -v:

Приложение должно гарантировать, что аргумент присваивания находится в той же форме, что и операнд присваивания. Указанное присвоение переменной должно произойти до выполнения программы awk, включая действия, связанные с шаблонами BEGIN (если они есть). Несколько вхождений этой опции могут быть указаны.

  • Смешано с именами файлов:

[...] Каждое такое присвоение переменной должно происходить непосредственно перед обработкой следующего файла , если таковой имеется. Таким образом, назначение перед первым аргументом файла должно выполняться после действий BEGIN (если они есть), тогда как назначение после последнего аргумента файла должно выполняться перед действиями END (если они есть). Если файловых аргументов нет, присваивания должны выполняться перед обработкой стандартного ввода.

Пример:

$ cat input 
hello
hello
$ awk -v var=one 'BEGIN{print var} /hello/{print var} END{print var}' \
    var=two input var=three input var=four
one
two
two
three
three
four

Вот это да! Это добавляет некоторые интересные контрольные точки ... это обязательно пригодится. Спасибо ...
Peter.O

1
Мое начальное "Ух ты!" все еще сохраняется, но это было несколько смягчено, посмотрев дальше в ответ Арсеге ... Я проверил его с реальным файлом с именем "var = three" ... awkдал преимущество тому, чтобы он был присваиванием переменной ... Это имеет большое следствие т.е. Во всех случаях, когда имя файла имеет такую ​​форму, оно будет проигнорировано, и переменная будет установлена ​​... Кажется, что единственный способ избежать этого столкновения - обеспечить, чтобы имена файлов для текущего рабочего каталога всегда были с префиксом с их относительным путем:./var=three
Peter.O

@ Peter.O, да, это также одна из причин -vвведения синтаксиса. Вы должны думать о -vсинтаксисе как о предпочтительном способе выполнения заданий в будущем.
dubiousjim

@ Peter.O, отличное замечание по поводу "gotcha", если имя файла является допустимым назначением переменной. Если вы используете переменную оболочки, содержащую имя файла и передающую его в качестве аргумента awk, вы можете использовать следующий улов:[ "$myfile" == "${myfile#/}" ] && myfile="./$myfile"
Подстановочный

4

Это старый стиль установки переменных извне в awk. Это было неоднозначно (что, если у вас есть имя файла foo=cat), поэтому в более поздних версиях добавили -vопцию. Вероятно, это должно работать для обратной совместимости, но вы не можете гарантировать. И, как я уже сказал, -vопция более новая, поэтому не все версии awkмогут ее поддерживать.


Ваш комментарий о возможности конфликта имен файлов хорош ... Я проверил его, и это определенно проблема. Я написал немного больше об этом в комментарии к ответу Мэта. Спасибо за освещение этой проблемы (+1)
Peter.O

2
На самом деле, как объяснено в [Mat s answer](http://unix.stackexchange.com/a/34258/9537), -v`, и назначение аргументов различается, когда они вступают в силу. Также -vнаходится в POSIX и должен присутствовать во всех, кроме самых древних из awkреализаций. Использование ./или проверка того, что имя файла содержит неидентифицирующий символ, вероятно, является наиболее надежным способом устранения неоднозначности.
jw013
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.