Comment échapper à un guillemet simple dans awk

111

Je veux faire ce qui suit

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

Mais échapper aux guillemets simples de cette façon ne fonctionne pas

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

Comment faire cela? Merci pour l'aide.

codeforester
la source
Un certain nombre de langues échappent aux guillemets en en mettant deux à la suite, peut-être essayez-le.
joshuahealy
J'ai essayé awk 'BEGIN {FS = "";} {printf "' '% s' '", $ 1}', mais aucun guillemet simple n'a été imprimé.
Cette page indique qu'il est impossible d'inclure un guillemet simple dans une chaîne entre guillemets simples. Vous devrez peut-être convertir en guillemets doubles.
joshuahealy
2
C'est impossible, mais deux chaînes shell adjacentes à guillemets simples se collent en un seul paramètre. Et deux chaînes shell à guillemets simples collées par des caractères non blancs se collent également dans un gros glob: 'abc'd'ef'is abcdef: literal plus dplus literal. Le dest en dehors des guillemets, et vous pouvez le remplacer dpar \'pour faire 'abc'\''ef'lequel évalue abc'ef.
Kaz

Réponses:

160

C'est peut-être ce que vous recherchez:

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

Autrement dit, avec '\''vous fermez l'ouverture ', puis imprimez un littéral 'en l'échappant et enfin ouvrez-le à 'nouveau.

Steve
la source
48
Cela n'a rien à voir avec awk. Le 'caractère ferme la 'chaîne littérale d' ouverture du shell. Le littéral du shell ne prend pas en charge un échappement de barre oblique inverse pour cela. La séquence '\''fait le tour: il ferme la simple citation littérale, précise le caractère de citation ( en utilisant une évasion qui est pris en charge en dehors de littéraux guillemets simples), puis ré-ouvre un nouveau single-citation littérale. Vous pouvez le considérer comme une séquence d'échappement de quatre caractères pour obtenir un guillemet simple. :)
Kaz
2
@Steve: Merci beaucoup pour votre réponse très utile. Vous m'avez sauvé beaucoup de maux de tête!
John Slegers du
4
@syntaxerror Les guillemets que vous utilisez pour préparer les arguments à appeler awkdépendent uniquement de l'interpréteur de commandes que vous utilisez pour composer les lignes de commande. Le '{printf $2}'devient un argument pour un execveappel système ou similaire, où il ressemble juste à une chaîne C terminée par null sans guillemets simples. Awk ne voit jamais les citations, ni sed. Vous pouvez en effet utiliser des guillemets doubles, mais des guillemets doubles n'empêche pas l'expansion de la coque $2, de sorte que vous devez échapper le signe dollar avec une barre oblique inverse pour le rendre littéral: "{printf \$2}".
Kaz le
4
@syntaxerror Par personnalisé, un script awk en ligne est généralement échappé par des guillemets simples, car la syntaxe awk contient souvent des éléments lexicaux qui sont spéciaux pour le shell, tels que des chaînes littérales entre guillemets doubles et des champs numérotés indiqués par des signes dollar. Si une expression régulière sed (ou autre) contient une syntaxe shell, vous devez également faire attention. sed -e "s/$FOO/$BAR/"ne fonctionnera pas si l'intention est de remplacer le texte littéral $FOOpar $BAR. Le moyen le plus simple serait sed -e 's/$FOO/$BAR/.
Kaz
1
@syntaxerror Si vous mettez les programmes awk entre guillemets, vous rencontrerez de nombreux échappements, comme awk "{ print \"abc\", \$1 }". Chaque fois qu'un guillemet double apparaît dans le programme awk, il doit être échappé pour qu'il ne ferme pas le guillemet du shell. Et comparez ceci: awk '{print "\\"}'(affichez une barre oblique inverse) à ce qu'il faut avec des guillemets doubles awk "BEGIN {print \"\\\\\" }":, Ouf! Les deux guillemets doivent être échappés et les deux contre-obliques. Le shell se convertit \\ en \ donc nous devons \\\\ encoder \\ .
Kaz le
76

Un guillemet simple est représenté par \x27

Comme dans

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

La source

tiagojco
la source
16
+1, mais il faut ajouter: \x27est une extension; POSIX Awk reconnaît uniquement \047. ( \47est ok aussi s'il n'est pas suivi d'un chiffre octal.)
hemflit
1
Comment finissez-vous \ x27 si vous avez un autre numéro après lui?
Jason Axelson
1
Jason, vous concaténez deux chaînes littérales: "AAA \ x27" "1". Ou vous utilisez simplement octal.
hemflit
9
Utilisez toujours octal ( \047), pas hex ( \x27), codes d'échappement - voir awk.freeshell.org/PrintASingleQuote .
Ed Morton
35

Une autre option consiste à passer le guillemet simple en tant que variable awk :

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

Exemple plus simple avec concaténation de chaînes:

# Prints 'test me', *including* the single quotes.
$ awk -v q=\' '{print q $0 q }' <<<'test me'
'test me'
mklement0
la source
5
Ceci est clair et concis, surtout si vous devez utiliser de nombreuses citations.
Peter Gluck
18
awk 'BEGIN {FS=" "} {printf "\047%s\047 ", $1}'
Sergio K
la source
1
Tant que je me souviens que \047c'est la séquence d'échappement octale pour le caractère guillemet simple, je trouve que cette alternative est la plus lisible.
Anthony Geoghegan
4

Pour les petits scripts, un moyen facultatif de le rendre lisible est d'utiliser une variable comme celle-ci:

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

Je l'ai trouvé pratique dans un cas où je devais produire plusieurs fois le caractère guillemet simple dans la sortie et le \ 047 le rendait totalement illisible

user1708042
la source