Como escapar de aspas simples dentro do awk

111

Eu quero fazer o seguinte

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

Mas escapar de aspas simples desta forma não funciona

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

Como fazer isso? Obrigado pela ajuda.

codeforester
fonte
Vários idiomas escapam das citações colocando dois deles em uma linha, talvez tente isso.
joshuahealy
Eu tentei awk 'BEGIN {FS = "";} {printf "' '% s' '", $ 1}', mas nenhuma aspa simples foi impressa.
Esta página diz que é impossível incluir aspas simples em uma string entre aspas simples. Talvez você precise converter para aspas duplas.
joshuahealy
2
É impossível, mas duas strings de shell adjacentes entre aspas simples se unem em um parâmetro. E duas strings de shell entre aspas simples coladas por caracteres sem espaço em branco também se unem em um grande globo: 'abc'd'ef'is abcdef: literal dmais literal. O destá fora das aspas e você pode substituí- dlo por \'para fazer o 'abc'\''ef'que avalia para abc'ef.
Kaz

Respostas:

160

Isso pode ser o que você está procurando:

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

Ou seja, com '\''você fechando a abertura ', imprima um literal 'escapando e finalmente abra 'novamente.

Steve
fonte
48
Não tem nada a ver com awk. O 'caractere fecha o 'literal de string do shell de abertura . O literal do shell não suporta um escape de barra invertida para isso. A sequência '\''faz o truque: ela fecha o literal de aspas simples, especifica o caractere de aspas (usando um escape que é suportado fora de literais de aspas simples) e, em seguida, reabre um novo literal de aspas simples. Você pode pensar nisso como uma sequência de escape de quatro caracteres para obter uma aspa simples. :)
Kaz
2
@Steve: Muito obrigado pela sua resposta muito útil. Você me salvou de muitas dores de cabeça!
John Slegers
4
@syntaxerror As aspas que você usa para preparar argumentos para invocar awksão puramente uma questão de interpretador de comandos que você está usando para compor linhas de comando. O '{printf $2}'é transformado em algum argumento para uma execvechamada de sistema ou semelhante, onde apenas se parece com uma string C terminada em null sem aspas simples. Awk nunca vê as aspas, e nem o sed. Você pode, de facto uso aspas, mas aspas duplas não impedem a expansão da shell de $2, assim que você tem que escapar do sinal de dólar com uma barra invertida para torná-lo literal: "{printf \$2}".
Kaz
4
@syntaxerror Por costume, um script awk in-line geralmente é escapado com aspas simples, porque a sintaxe awk geralmente contém elementos lexicais que são especiais para o shell, como strings literais com aspas duplas e campos numerados indicados por cifrões. Se uma expressão regular sed (ou qualquer outra) contiver sintaxe de shell, você também deve ter cuidado. sed -e "s/$FOO/$BAR/"não funcionará se a intenção for substituir o texto literal $FOOpor $BAR. A maneira mais fácil seria sed -e 's/$FOO/$BAR/.
Kaz
1
@syntaxerror Se você colocar programas awk entre aspas duplas, terá muitos escapes, como awk "{ print \"abc\", \$1 }". Sempre que uma aspa dupla aparecer no programa awk, ela deve ser escapada para que não feche as aspas do shell. E compare isso: awk '{print "\\"}'(imprima uma barra invertida) com o que é preciso com aspas duplas: awk "BEGIN {print \"\\\\\" }"Ufa! Ambas as aspas devem ter escape e ambas as barras invertidas. O shell converte \\ para, \ portanto, precisamos \\\\ codificar \\ .
Kaz
76

Uma aspa simples é representada usando \x27

Como em

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

Fonte

tiagojco
fonte
16
+1, mas precisa adicionar: \x27é uma extensão; POSIX Awk apenas reconhece \047. (também \47está bem se não for seguido por um dígito octal.)
hemflit
1
Como você termina \ x27 se tiver outro número depois dele?
Jason Axelson
1
Jason, você concatena dois literais de string: "AAA \ x27" "1". Ou você apenas usa octal.
hemflit
9
Sempre use octal ( \047), não hex ( \x27), códigos de escape - consulte awk.freeshell.org/PrintASingleQuote .
Ed Morton
35

Outra opção é passar as aspas simples como uma variável awk :

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

Exemplo mais simples com concatenação de string:

# Prints 'test me', *including* the single quotes.
$ awk -v q=\' '{print q $0 q }' <<<'test me'
'test me'
mklement0
fonte
5
Isso é claro e conciso, especialmente se você precisar usar muitas citações.
Peter Gluck
18
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'
Sergio K
fonte
1
Contanto que me lembre que essa \047é a sequência de escape octal para o caractere de aspas simples, considero essa alternativa a mais legível.
Anthony Geoghegan
4

Para pequenos scripts, uma maneira opcional de torná-los legíveis é usar uma variável como esta:

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

Achei conveniente em um caso em que tive que produzir muitas vezes o caractere de aspas simples na saída e o \ 047 o tornava totalmente ilegível

user1708042
fonte