web-dev-qa-db-fra.com

Pourquoi sed nécessite-t-il 3 barres obliques inverses pour une barre oblique inverse régulière?

Je suis curieux de savoir pourquoi sed a besoin de 3 \ juste pour en reconnaître un? Je comprendrais qu'il en faudrait 2, mais 3 non.

EDIT: voici un exemple sur mon ordinateur Windows, en utilisant Cygwin:

echo "sample_input\whatever" | sed "s/\\\/\//"

Si je n'ajoute pas 3 barres obliques inverses, j'obtiens un

sed: -e expression #1, char 7: unterminated s' command
41
Geo

J'ai pu reproduire ce comportement en utilisant Vista et Cygwin 1.7.0.

  • Deux barres obliques inverses produisent l'erreur
  • soit trois ou quatre barres obliques inverses fonctionnent
  • Cinq donne la même erreur

Deux barres obliques inverses deviennent une seule barre oblique inversée dans le shell qui, dans sed, échappe à la barre oblique qui est le délimiteur central.

\\/ -> \/ (which makes the forward slash a regular character instead of a delimiter)

Trois d'entre eux: Les deux premiers deviennent un dans le Shell qui échappent ensuite au troisième dans sed

\\\/ -> \\/

Quatre: Chaque paire devient unique dans la coquille, puis la première résultante échappe à la seconde dans sed

\\\\/ -> \\/ 

Modifier:

Oh, j'ai oublié de dire que les guillemets simples et les guillemets doubles fonctionnaient de la même manière pour moi (cmd.exe ne fait pas la distinction que Bash, et al, fait).

41

Votre Shell (probablement bash) fait sa propre fuite, ce qui vous déroute. Vous pouvez utiliser une commande echo pour voir ce qui est passé, ou il est facile d'écrire un programme personnalisé (communément appelé "showargs" ou similaire):

 $ echo "s /\\\/\//""..____.] s /\\/\//}.____. ____.] s /\/\////.____.]

Vous pouvez également utiliser des guillemets simples, qui sont traités différemment dans bash.

12
Roger Pate

Cela est dû à la règle d'analyse des chaînes entre guillemets doubles de sh.

Posix spécifie comment sh analyse les chaînes entre guillemets.

La barre oblique inversée doit conserver sa signification spéciale en tant que caractère d'échappement (voir Caractère d'échappement (barre oblique inverse)) uniquement lorsqu'elle est suivie par l'un des caractères suivants lorsqu'elle est considérée comme spéciale: $ `" \

En d'autres termes, sh laisse la barre oblique inverse qui est suivie par des caractères autres que $ '".

Donc, si sh rencontre la chaîne entre guillemets sed "s/\\\/\//", sh l'analyse comme suit.

  1. Les deux premiers \\ est remplacé par \. Parce que le premier \ est suivi du deuxième \.
  2. Les troisième et quatrième \ est toujours laissé dans la chaîne. Parce que les deux sont suivis de /, ce qui n'est pas spécial dans les chaînes entre guillemets.

Après le pasring, sh passe la chaîne s/\\/\// à sed, qui remplace la première occurrence de \ en /.

Avec le même raisonnement, lorsque sh rencontre la chaîne, "sed s/\\\\/\//", sh passe /\\/\// à sed, qui remplace également la première occurrence de \ en /.

6
MS.Kim

Veuillez montrer un exemple de ce que vous avez à l'avenir. dans sed, dites que vous voulez remplacer un "\ "avec pipe (|), par exemple

$ cat file
asklfja \ asf

$ sed 's/\\/|/g' file
asklfja | asf

$ sed 's%\\%|%g' file #using different delimiter
asklfja | asf

vous avez juste besoin d'y échapper une fois.

Edit: Pour l'exemple de @ OP, puisque vous utilisez cmd.exe et non bash/ksh, cmd.exe n'aime pas les guillemets simples. Je ne peux pas produire votre scénario. Cela fonctionne pour mon GNU sed sur les fenêtres utilisant 2 barres obliques

par exemple

C:\test>echo "sample_input\whatever" | sed "s/\\/\//"
"sample_input/whatever"
4
ghostdog74

Dans ma version de CYGWIN, cela fonctionne comme l'indique l'affiche originale, mais fonctionne différemment (normalement) si j'utilise des guillemets simples.

 $ echo "sample_input\any" | sed 's /\\/\//'
 sample_input/quel que soit 
 $ echo "sample_input\any" | sed "s /\\/\//"
 sed: -e expression # 1, caractère 7: commande` s 'non terminée 

Hmmm ..

1
James K

Remplacer une barre oblique inverse par deux sur mon Cygwin nécessite cette expression:

sed -e "s | \\ | \\\\ | g"

0
OutputLogic

Je suppose que vous supposez \\\n ou \\\t comme trois barres obliques inverses, mais en fait, ses 2 barres obliques inverses et un autre motif

   backslash          \\
   newline            \n
   tab                \t

aussi, / pourrait avoir besoin de s'échapper car dans s/.../, / utilise pour ouvrir et fermer les pièces.

donc /\\\/\// serait \\ + \/ + \/ selon votre exemple mis à jour

0
YOU