Должен ли awk расширять escape-последовательности в назначенных переменных командной строки?

Недавно я обнаружил, что синтаксис Awk -v VAR=VAL для инициализации переменных в командной строке расширяет escape-последовательности в VAL. Раньше я думал, что это хороший способ передать строки в Awk без необходимости сначала запускать над ними функцию экранирования.

Например, следующий скрипт:

awk -v VAR='x\tx' 'BEGIN{printf("%s\n", VAR);}'

я рассчитывал напечатать

x\tx

но на самом деле печатает:

x       x

В стороне: переменные среды для передачи строк в неизмененном виде, этот вопрос не спрашивает, как получить поведение, которое я ожидал ранее.

Вот что справочная страница говорит по этому поводу:

-v var=val, --assign var=val Присвоить значение val переменной var перед началом выполнения программы. Такие значения переменных доступны в блоке BEGIN программы AWK.

И еще ниже:

Строковые константы Строковые константы в AWK – это последовательности символов, заключенные в двойные кавычки (например, "значение"). Внутри строк распознаются определенные escape-последовательности, как в C. Это:

... список управляющих последовательностей ...

Управляющие последовательности также могут использоваться внутри постоянных регулярных выражений (например, /[ \t\f\n\r\v]/ соответствует пробельным символам).

В режиме совместимости символы, представленные восьмеричными и шестнадцатеричными управляющими последовательностями, обрабатываются буквально при использовании в константах регулярных выражений. Таким образом, /a\52b/ эквивалентно /a*b/.

Насколько я понимаю, val в -v var=val не является строковой константой, и нет текста, указывающего, что применяются правила экранирования строковых констант.

Мои вопросы:

  1. Есть ли более авторитетный источник языка awk, чем справочная страница, и если да, то что в нем указано?
  2. Что POSIX может сказать по этому поводу?
  3. Все ли версии Awk ведут себя таким образом, т. е. могу ли я полагаться на выполнение расширения, если я действительно этого хочу?

person je4d    schedule 10.12.2012    source источник
comment
@shellter это не оператор печати, я использовал printf %s, чтобы избежать этого. Для получения дополнительных доказательств попробуйте использовать gsub или length, результаты показывают, что расширение выполняется до запуска сценария awk.   -  person je4d    schedule 11.12.2012


Ответы (1)


Присваивание является строковой константой.

Соответствующие разделы из стандарта:

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

и

Операнд, начинающийся со знака подчеркивания или буквы из переносимого набора символов (см. таблицу в XBD Portable Character Set), за которым следует последовательность символов подчеркивания, цифр и букв из переносимого набора символов, за которым следует символ '=' , должно указывать назначение переменной, а не имя пути. Символы перед '=' представляют имя переменной awk; если это имя является зарезервированным словом awk (см. Грамматика), поведение не определено. Символы, следующие за ‹знаком равенства›, должны интерпретироваться так, как если бы они появились в программе awk с предшествующим и последующим символом двойной кавычки ( ' )', как токен STRING (см. Грамматика), за исключением случаев, когда последний символ неэкранированный, он должен интерпретироваться как литерал, а не как первый символ последовательности "\""

person William Pursell    schedule 10.12.2012