Как избежать одиночной кавычки внутри awk

111

Я хочу сделать следующее

awk 'BEGIN {FS=" ";} {printf "'%s' ", $1}'

Но такой способ экранирования одинарной кавычки не работает

awk 'BEGIN {FS=" ";} {printf "\'%s\' ", $1}'

Как это сделать? Спасибо за помощь.

codeforester
источник
Некоторые языки избегают кавычек, помещая два из них в ряд, возможно, попробуйте это.
joshuahealy
Я попробовал awk 'BEGIN {FS = "";} {printf "' '% s' '", $ 1}', но одиночная кавычка не была напечатана.
На этой странице сказано, что включение одинарной кавычки в строку, заключенную в одинарные кавычки, невозможно. Возможно, вам придется преобразовать в двойные кавычки.
joshuahealy
2
Это невозможно, но две соседние строки оболочки в одинарных кавычках сливаются в один параметр. И две строки оболочки в одинарных кавычках, склеенные непробельными символами, также склеиваются в один большой глобус: 'abc'd'ef'is abcdef: literal plus dplus literal. Это dнаходится за пределами кавычек, и вы можете заменить dего \'на make, 'abc'\''ef'который оценивается abc'ef.
Kaz

Ответы:

160

Возможно, это то, что вы ищете:

awk 'BEGIN {FS=" ";} {printf "'\''%s'\'' ", $1}'

То есть '\''вы закрываете отверстие ', затем печатаете литерал ', экранируя его, и, наконец, 'снова открываете .

Стив
источник
48
Это не имеет ничего общего с awk. Символ 'закрывает открывающий 'строковый литерал оболочки. Литерал оболочки не поддерживает для этого экранирование обратной косой черты. Последовательность '\''делает трюк: он закрывает одинарную кавычку буквальной, указует на символ кавычки (используя побег , который будет поддерживаются вне одиночных кавычек литералов) , а затем повторно открывает новые одинарные кавычки буквально. Вы можете думать об этом как о четырехсимвольной escape-последовательности для получения одинарной кавычки. :)
Kaz
2
@ Стив: Большое спасибо за очень полезный ответ. Вы избавили меня от головной боли!
Джон Слегерс
4
@syntaxerror Какие кавычки вы используете для подготовки аргументов для вызова awk, зависит исключительно от интерпретатора команд, который вы используете для составления командных строк. Преобразование '{printf $2}'превращается в некоторый аргумент для execveсистемного вызова или аналогичного, где он просто выглядит как строка C с завершающим нулем без каких-либо одинарных кавычек. Awk никогда не видит кавычек, как и sed. Вы можете фактически использовать двойные кавычки, но двойные кавычки не препятствуют экспансии командного интерпретатора из $2, так что вы должны бежать знак доллара с обратной косой черты , чтобы сделать его буквальным: "{printf \$2}".
Kaz
4
@syntaxerror По обычаю встроенный сценарий awk обычно экранируется одинарными кавычками, потому что синтаксис awk часто содержит лексические элементы, которые являются специальными для оболочки, такие как строковые литералы в двойных кавычках и нумерованные поля, обозначенные знаками доллара. Если регулярное выражение sed (или что-то еще) содержит синтаксис оболочки, вы также должны быть осторожны. sed -e "s/$FOO/$BAR/"не будет работать, если намерение состоит в том, чтобы заменить буквальный текст $FOOна $BAR. Самый простой способ был бы sed -e 's/$FOO/$BAR/.
Kaz
1
@syntaxerror Если вы заключите awk-программы в двойные кавычки, вы столкнетесь с множеством экранирований, например awk "{ print \"abc\", \$1 }" . Каждый раз, когда в программе awk появляется двойная кавычка, ее нужно экранировать, чтобы она не закрывала кавычку оболочки. И сравните это: awk '{print "\\"}'(напечатайте обратную косую черту) с двойными кавычками:, awk "BEGIN {print \"\\\\\" }"Уф! Обе кавычки должны быть экранированы, и обе обратные косые черты. Оболочка преобразуется \\ в, \ поэтому нам нужно \\\\ кодировать \\ .
Kaz
76

Одиночная кавычка представлена ​​с использованием \x27

Как в

awk 'BEGIN {FS=" ";} {printf "\x27%s\x27 ", $1}'

Источник

Tiagojco
источник
16
+1, но нужно добавить: \x27это расширение; POSIX Awk распознает только файлы \047. ( \47тоже нормально, если за ним не следует восьмеричная цифра.)
hemflit
1
Как закончить \ x27, если после него стоит другой номер?
Джейсон Аксельсон
1
Джейсон, вы объединяете два строковых литерала: «AAA \ x27» «1». Или вы просто используете восьмеричное.
hemflit
9
Всегда используйте восьмеричные ( \047), а не шестнадцатеричные ( \x27) escape-коды - см. Awk.freeshell.org/PrintASingleQuote .
Эд Мортон
35

Другой вариант - передать одинарную кавычку как переменную awk :

awk -v q=\' 'BEGIN {FS=" ";} {printf "%s%s%s ", q, $1, q}'

Более простой пример с конкатенацией строк:

# Prints 'test me', *including* the single quotes.
$ awk -v q=\' '{print q $0 q }' <<<'test me'
'test me'
mklement0
источник
5
Это ясно и кратко, особенно если вам нужно использовать много цитат.
Питер Глюк,
18
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'
Серджио К
источник
1
Пока я помню, что \047это восьмеричная escape-последовательность для символа одиночной кавычки, я считаю эту альтернативу наиболее читаемой.
Энтони
4

Для небольших скриптов необязательным способом сделать его читабельным является использование такой переменной:

awk -v fmt="'%s'\n" '{printf fmt, $1}'

Я обнаружил, что это удобно в том случае, когда мне приходилось много раз выводить символ одинарной кавычки в выводе, а \ 047 делали его полностью нечитаемым

user1708042
источник