Чи є 2 способи встановити awk vars за допомогою командного рядка?


10

Я помітив приклад O'Reilly awk(1997), який призначив змінну awk, встановивши її в командному рядку після тексту тексту програми. Це працює, але я не можу знайти цей синтаксис у людині / 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

Оце Так! Це додає декількох цікавих контрольних точок ... це обов'язково стане в нагоді. Дякую ...
Пітер.О

1
Мій початковий "Ого!" як і раніше, але це було дещо загартовано, дивлячись далі на відповідь Арсега ... Я перевірив його з реальним файлом під назвою "var = three" ... awkнадав перевагу тому, що воно є змінним завданням ... У цьому є головний висновок , тобто. У всіх випадках, коли ім'я файлу має таку форму, воно буде ігноруватися, і змінна буде встановлена ​​... Схоже, єдиний спосіб уникнути цього зіткнення - це гарантувати, що імена файлів для поточного робочого каталогу завжди мають бути встановлені префіксами з їх відносним шляхом:./var=three
Пітер.О

@ Peter.O, так, це теж одна з причин введення -vсинтаксису. Ви повинні думати про -vсинтаксис як про кращий спосіб виконання завдань, рухаючись вперед.
сумнівним

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

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.