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.
la source
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.Ce lien décrit bash Quotes and Escaping
Votre question porte sur les trois premières sections.
Vous trouverez ci-dessous un tableau de la façon dont les chaînes au fur et à mesure les
bash
transmettentgrep
et commentgrep
les interpréter en interne.Voyons d'abord
echo "#ab\\cd" > file
.Dans les guillemets faibles ("")
"#ab\\cd"
, le\\
est un échappé\
qui est passé àfile
un seul littéral\
. Donc,file
contientab\cd
Maintenant, à vos commandes: Le tableau ci-dessous peut aider à voir ce qui se passe réellement avec chaque appel. Le
*
affiche ceux qui correspondent au contenu du fichier. Il s'agit vraiment d'appliquer les règles d'échappement de bash, comme sur la page Web, avec une note particulière à la réponse de Daniel Kullmann où il fait référence à un comportement d'évasion dans une situation de citation faible .la source