J'ai récemment rencontré des problèmes avec certaines expressions rationnelles sur la ligne de commande et j'ai constaté que pour faire correspondre une barre oblique inverse, différents nombres de caractères peuvent être utilisés. Ce nombre dépend de la citation utilisée pour l'expression régulière (aucune, guillemets simples, guillemets doubles). Voir la session bash suivante pour ce que je veux dire:
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
Cela signifie que:
- sans guillemets, je peux associer une barre oblique inverse à 4 à 7 barres obliques inverses réelles
- avec des guillemets doubles, je peux associer une barre oblique inverse à 3-6 barres obliques inverses réelles
- Avec des guillemets simples, je peux associer une barre oblique inverse à 2-3 barres obliques inverses réelles
Je comprends qu'une barre oblique inverse supplémentaire est ignorée par le shell (à partir de la page de manuel bash):
"Une barre oblique inversée (\) est le caractère d'échappement. Il conserve la valeur littérale du caractère suivant qui suit"
Cela ne s'applique pas aux exemples entre guillemets simples, car aucun échappement n'est effectué entre guillemets simples.
Et une barre oblique inverse supplémentaire est ignorée par la commande grep ("\ c" est juste "c" échappé, mais c'est exactement la même chose que "c", parce que "c" n'a pas de signification particulière dans une expression régulière).
Cela explique le comportement de l'exemple avec des guillemets simples, mais je ne comprends pas vraiment les deux autres exemples, en particulier pourquoi il y a une différence entre les chaînes non-qouted et les guillemets doubles.
Encore une fois, une citation de la page de manuel bash:
"L'insertion de caractères entre guillemets doubles préserve la valeur littérale de tous les caractères entre guillemets, à l'exception de $,`, \, et, lorsque l'expansion de l'historique est activée,!. "
J'ai essayé la même chose avec GNU awk (par exemple awk /ab\cd/{print} file
), avec les mêmes résultats.
Perl, cependant, montre des résultats différents (en utilisant par exemple perl -ne
"/ab\\cd/"\&\&print file
):
- sans guillemets, je peux associer une barre oblique inverse à 4-5 barres obliques inverses réelles
- avec des guillemets doubles, je peux associer une barre oblique inverse à 3-4 barres obliques inverses réelles
- Avec des guillemets simples, je peux associer une barre oblique inverse à 2 barres obliques inverses réelles
Quelqu'un peut-il expliquer cette différence entre des chaînes d'expression régulière non citées et à double qouted sur la ligne de commande pour grep et awk? Je ne suis pas très intéressé par une explication du comportement de Perl, car je n'utilise généralement pas de lignes simples Perl.
printf "\ntest"
va insérer une nouvelle ligne avant "test", même si elle"\n"
aurait dû être traduite"n"
par le shell comme elle est entre guillemets ... (donc le résultat attendu devrait être, pour "\ ntest", "ntest". Nous devrions prendre l'habitude d'écrire:printf "\\ntest"
ouprintf '\ntest'
, mais d'une manière ou d'une autre je vois beaucoup de script s'appuyant sur l'étrange à la place.