Pourquoi `echo -e“ \\\ SOME_TEXT ”` n'affiche qu'une seule barre oblique inverse?

19

Quelqu'un pourrait-il expliquer ce qui se passe dans les coulisses des personnages qui s'échappent dans le shell Linux? J'ai essayé ce qui suit et j'ai beaucoup cherché sur Google, sans réussir à comprendre ce qui se passe (et comment):

root@sv01:~# echo -e "\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\\ Hello!"
\\\ Hello!
root@sv01:~# echo -e "\n Hello!"

 Hello!
root@sv01:~# echo -e "\\n Hello!"

 Hello!
root@sv01:~# echo -e "\\\n Hello!"
\n Hello!

Je suis totalement perdu là-bas, alors par exemple, pourquoi trois barres obliques inverses ne donnent-elles qu'une seule barre oblique inverse? Je m'attendrais à ce que les deux premiers soient échappés à un, le troisième ne trouverait rien à échapper donc il resterait une barre oblique (ligne dans la première expérience), mais ce qui se passe, c'est que le troisième est juste disparaît.
Pourquoi je reçois une barre oblique inverse sur quatre \\\\ Hello? Je m'attends à ce que chaque paire donne une barre oblique inverse -> deux barres obliques inverses.

Et pourquoi ai-je besoin de trois barres obliques inverses dans le dernier cas pour m'échapper \ n? que se passe-t-il en arrière-plan de s'échapper pour l'obtenir? et en quoi est-ce différent du \\ncas?

J'apprécie toute explication de ce qui se passe dans les lignes précédentes.

Mohammed Noureldin
la source
echo -ele comportement n'est de toute façon pas défini par les normes - voir pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html . La sortie est complètement définie par l'implémentation s'il y a une barre oblique inverse littérale n'importe où dans les entrées, et la seule option autorisée est -n(ce qui signifie qu'une implémentation conforme aux normes aura une echo -eimpression -esur sa sortie).
Charles Duffy
... même si vous êtes sûr à 100% que votre shell est bash, même alors ce echo -e n'est pas sûr: echose comportera conformément à la norme si les deux options posixet xpg_echoles options d'exécution sont activées, ou si elles sont compilées avec des options de construction équivalentes. La pratique sécuritaire consiste à utiliser à la printfplace - voir les sections UTILISATION DE L'APPLICATION et JUSTIFICATION du lien ci-dessus décrivant comment faire printfagir en remplacement echo.
Charles Duffy

Réponses:

28

C'est parce que bashet echo -ecombiné. Deman 1 bash

Une barre oblique inverse non citée ( \) est le caractère d'échappement. Il conserve la valeur littérale du caractère suivant qui suit, à l'exception de <newline>. […]

Caractères Enfermer guillemets préserve la valeur littérale de tous les caractères dans les citations, à l'exception $, `, \[...] La barre oblique inverse conserve sa signification que lorsqu'il est suivi par l' un des caractères suivants: $,`, ", \ou <newline>.

Le fait est que la barre oblique inverse entre guillemets n'est pas toujours spéciale.

Il existe différentes implémentations de echoen général, c'est une fonction intégrée bash; l'important ici est ce comportement:

Si -eest en vigueur, les séquences suivantes sont reconnues:
\\
barre oblique inverse
[…]
\n
nouvelle ligne

Maintenant, nous pouvons décoder:

  1. echo -e "\ Hello!"- rien de spécial pour bash, rien de spécial pour echo; \reste.
  2. echo -e "\\ Hello!"- le premier \dit bashde traiter le second \littéralement; echoobtient \ Hello!et agit comme ci-dessus.
  3. echo -e "\\\ Hello!"- le premier \dit bashde traiter le second \littéralement; echoobtient \\ Hello!et (à cause de -e) il reconnaît \\comme \.
  4. echo -e "\\\\ Hello!"- le premier \dit bashde traiter le second \littéralement; le troisième en dit autant du quatrième; echoobtient \\ Hello!et (à cause de -e) il reconnaît \\comme \.
  5. echo -e "\\\\\ Hello!"- le premier \dit bashde traiter le second \littéralement; le troisième en dit autant du quatrième; le dernier n'est pas spécial; echoobtient \\\ Hello!et (à cause de -e) il reconnaît l'initiale \\comme \, la dernière \reste intacte.

Etc. Comme vous pouvez le voir, jusqu'à quatre barres obliques inverses consécutives donnent un résultat. C'est pourquoi vous en avez besoin (au moins) neuf pour en obtenir trois. 9 = 4 + 4 + 1.

Maintenant avec \n:

  1. echo -e "\n Hello!"- il n'y a rien de spécial bash, echo obtient la même chaîne et (à cause de -e) il interprète \ncomme une nouvelle ligne.
  2. echo -e "\\n Hello!"- bashinterprète \\comme \; echoobtient \n Hello!et le résultat est le même que ci-dessus.
  3. echo -e "\\\n Hello!"- bashinterprète l'initiale \\comme \; echoobtient \\n Hello!et (à cause de -e) il interprète \\comme un littéral\ qui doit être imprimé.

Les résultats seraient différents avec 'au lieu de "(en raison d'un bashcomportement différent ) ou sans -e( echocomportement différent ).

Kamil Maciorowski
la source
1
Merci beaucoup! Il y a donc deux étapes qui s'échappent, l'étape effectuée par bash, et la seconde par les -ejuges, le texte déjà jugé par bash, n'est-ce pas? si c'est correct, cela élimine la confusion. Pourriez-vous peut-être nous dire comment sedse comporte a-t-il sa propre technique d'évasion? donc je veux dire que ça se comporte comme un écho avec -e?
Mohammed Noureldin
2
@MohammedNoureldin Oui, il y a deux étapes. Votre question d'origine est très bien telle qu'elle est, ne la rendons pas trop compliquée sed. Vous pouvez cependant poser une autre question (à propos de sedseulement), faites d'abord vos propres recherches.
Kamil Maciorowski
3
@MohammedNoureldin sedsuivra les mêmes principes de base: bash interprétera la ligne de commande selon ses règles, analysant (et peut-être supprimant) les guillemets et les échappements. Le résultat est transmis à sed, qui l'interprète selon ses règles d'échappement. BTW, vous pouvez simplifier cela en utilisant une chaîne entre guillemets simples bash, car cela n'a pas d'interprétation d'échappement eny effectuée (par bash) - bash supprime les guillemets simples et transmet ce qui s'y trouve directement à la commande.
Gordon Davisson
J'ai toujours un petit problème au echo -e "\\\n Hello!"cas où. Ici bash fera s'échapper, et il deviendra \\n, puis -eéchappera aux deux barres obliques inversées résultantes \\net ensuite elles deviendront \n. maintenant qui interprète \npour en faire une nouvelle ligne? Normalement, dans le cas de echo -e "\n Hello!", bash ne fait rien et -einterprète \ncomme une nouvelle ligne. mais dans la première situation mentionnée, le processus d'interprétation a été fait avant de se \nfaire interpréter. Pourriez-vous expliquer cela s'il vous plaît?
Mohammed Noureldin
1
Ok ma faute, j'ai lu ça pendant 2 jours avec leurs nuits, donc apparemment j'ai commencé à mélanger les cas, je crois que j'ai quelque chose d'autre sedqui m'a dérouté hier soir (peut-être que j'ai fait quelque chose de mal hier), mais maintenant je réessayé la même chose avec echo -eet sed, et j'ai eu la même chose que excepté, merci!
Mohammed Noureldin