5 votes

Pourquoi les crochets "][" ont-ils besoin d'un double échappement ? \\ "pour empêcher l'interprétation par le Shell ?

J'utilise 'bash' Shell et j'exécute la commande 'awk' ci-dessous sur un fichier dont les enregistrements sont séparés par un certain nombre de caractères différents comme les parenthèses, les deux points, les parenthèses comme l'exemple d'enregistrement suivant

...(field#13[field#14:]]:filed#18[filed#19)[...

Cependant, lorsque j'échappe "][" avec l'échappement simple '\', la commande awk échoue et je dois utiliser l'échappement double '\'. \\ Comment est-il nécessaire d'utiliser des crochets à double échappement (dans 'csh' Shell c'est pareil) ?

awk -F"[\\[\\]:)(]" '{print $18}' inFile
filed#18

Veuillez également noter que je sais que je peux les échapper avec un double échappement '. \\ comme ci-dessous, je veux juste savoir pourquoi pour les parenthèses c'est obligatoire ?

awk -F"[\\[\\]\\:\\)\\(]" '{print $18}' inFile
filed#18

même l'utilisation de l'échappement de signe donne l'avertissement (sauf pour les parenthèses), mais toujours l'exécution de la commande et le résultat venant, merci.

awk -F '[\\[\\]\:\)\(]' '{print $18}' inFile
awk: warning: escape sequence `\:' treated as plain `:'
awk: warning: escape sequence `\)' treated as plain `)'
awk: warning: escape sequence `\(' treated as plain `('
filed#18

3voto

Stewart Points 1385

Il y a plusieurs niveaux de citation/escapage ici. D'abord, vous avez votre FS regex ( -F "[\\[\\]\:\)\(]" ) entre guillemets. C'est ce qui donne les avertissements :

$ awk -F"[\\[\\]:)(]" '{print $2}' file 
awk: warning: escape sequence `\[' treated as plain `['
awk: warning: escape sequence `\]' treated as plain `]'
awk: fatal: :, [., or [=: /[[]:)(]/

Alors que les guillemets simples fonctionnent tout simplement :

$ awk -F'[\\[\\]:)(]' '{print $2}' file 
field#13

C'est parce que tout ce qui est entre guillemets doubles est d'abord développé par le Shell. Ainsi, le Shell développe en premier lieu \\[ a \[ et le passe ensuite à awk. Vous pouvez voir ce qui se passe avec set -x :

$ set -x
$ awk -F"[\\[\\]:)(]" '{print $2}' file 
+ awk '-F[\[\]:)(]' '{print $2}' file

Comme vous pouvez le voir ci-dessus, le Shell a mangé le premier échappement. Donc n'utilisez pas " du tout ici.

Le problème suivant est que l'awk lui-même interprète les échappements deux fois. Parce que les -F peut accepter des échappatoires spéciales comme \t y \r etc., il essaiera d'abord de lire \[ comme un seul caractère échappé. Depuis \[ est la même chose que [ (contrairement à, disons \n ce qui n'est pas la même chose que n desde \n est un saut de ligne), il vous donne un message d'avertissement, expliquant qu'il a traité \[ como [ .

Donc, vous avez besoin du premier échappement pour échapper à la \ lui-même, et la deuxième échappatoire pour échapper à la [ . En d'autres termes, en \\[ le 1er \ échappe à la deuxième \ afin que ce qui awk reçoit finalement est \[ .

Il serait peut-être plus facile de comprendre si vous considérez quelque chose comme ceci :

$ echo -e 'a\tb'
a   b                  ## prints a tab character
$ echo -e 'a\\tb'
a\tb                   ## prints a literal \t
$ echo -e "a\\tb"      
a   b                  ## prints a tab because of the double quotes
$ echo -e "a\\\tb"     
a\tb                   ## 3ple escaping! Prints a literal `\t` again.

Le dernier exemple ci-dessus est le plus parlant. Puisque la chaîne de caractères à renvoyer est entre guillemets doubles, elle est d'abord développée par le Shell (qui en mange un). \ ), alors par echo -e (qui mange un autre \ ) et est finalement imprimé comme un littéral \t .

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X