Comment faire echo
et printf
traiter antislashs dans zsh
, bash
et d' autres obus?
Sous zsh, j'obtiens le comportement suivant:
$ echo "foo\bar\baz"
foaaz
$ echo "foo\\bar\\baz"
foaaz
$ echo 'foo\bar\baz'
foaaz
$ echo 'foo\\bar\\baz'
foo\bar\baz
Sous bash , les choses semblent un peu plus cohérentes:
bash$ echo "foo\bar\baz"
foo\bar\baz
bash$ echo 'foo\bar\baz'
foo\bar\baz
bash$
Mais plus concrètement: comment passer une chaîne contenant des barres obliques inverses comme\\foo\bar\something
:
echo
printf
print
et obtenir exactement la même chaîne? (en zsh
et bash
)?
Voici une autre expérience avec des fonctions dans zsh:
function foo
{
echo -E '$1'
}
$ foo \\here\is\some\path
$1
Comment puis-je simplement l'imprimer \\here\is\some\path
?
Mise à jour (Remarque: il a maintenant été répondu dans le commentaire de Stéphane)
J'ai essayé ce qui suit dans zsh 5.0.2:
function foo
{
printf '$s\n' $1
}
foo '\\some\path'
Mais cela imprime $s
?
printf
,echo
n'est pas portable à cet égard.'
par"
, et invoquez-la avec: foo '\\ ici \ est \ un \ chemin' (sinon le shell appelant a la possibilité d'interpréter le '\' avant d'arriver à la fonction)'$s\n'
alors qu'elle aurait dû utiliser'%s\n'
.Réponses:
zsh
echo
se comporte de manière standard, commebash
en mode UNIX. C'est-à-dire qu'il se développe\b
au caractère ASCII BS comme l'exige la spécification UNIX.Ne pas utiliser
echo
pour afficher des chaînes arbitraires, utilisezprintf
:print -r -- "$1"
fonctionne également mais estksh
/zsh
spécifique.echo -E - "$1"
travailler aveczsh
et je crois que certains BSD.fonctionne dans n'importe quel shell de type Bourne, même ceux de quelques décennies où il n'y avait pas de
printf
commande, mais il engendre un nouveau processus, et n'est vraiment pas nécessaire de nos jours comme nous l'avons maintenantprintf
partout.Et en passant, vous devez échapper les barres obliques inverses sur une ligne de commande du shell car c'est spécial pour le shell (tous les shell sauf
rc
), donc:foo \\foo\bar
passerait la"\foo\bar"
chaîne àfoo
laquelle ne peut pas réinventer la barre oblique inversée perdue.la source
printf '%s\n' "$var"
fonctionne pour moi sur la ligne de commande (zsh 5.0.2
c'est-à-dire la dernière), mais pas à l'intérieur d'une fonction (voir ma mise à jour dans l'OP). Pourquoi?printf '%s\n'
pasprintf '$s\n'
ce que tu veux. Notez que vous devez citer des variables dans d'autres shells quezsh
("$1"
, not$1
) et la syntaxe de définition de fonction standard estfoo() { ...; }
, bien que n'importe quel shell, maisbash
allowfoo() any-command
, etfunction foo { .... }
est laksh
syntaxe.nouvelle réponse: read -r var
et pour afficher:
devrait marcher.
Donc pour votre fonction foo:
ancienne réponse ci-dessous (ne répond pas, mais peut-être utile ^^)
remplacez simplement chacun
\
par\\
pour dire au shell "que c'est un littéral que\
je veux". sinon (par exemple dans zsh, dans votre exemple), cela pourrait bien\b
signifier "1 retour arrière", ou autre chose.vous pouvez par exemple utiliser sed:
(voyez comment vous devez également y échapper "\", pour dire à sed la même chose: "c'est un littéral" \ "je veux) (et remarquez que je l'entoure de '' et non" "pour éviter que le shell interprète la plupart aussi)
la source
read -r var
semble attendre la contribution deSTDIN
. Et si je le passe en argument? (ex. foo\\here\is\some\path
)D'une manière générale, vous ne pouvez pas, car la barre oblique inverse est le caractère d'échappement (et en tant que tel doit être échappé lorsque sa valeur littérale est requise). BASH fournit des guillemets simples à cet effet, mais vous ne pouvez pas utiliser d'échappement un guillemet simple dans une chaîne entre guillemets simples.
Quant à la
echo
différence, il s'agit d'un intégré qui peut se comporter différemment selon les coques (dans une certaine mesure). Par exemple, le BASH intégré a une-e
option qui lui dit d'interpréter les séquences de barre oblique inverse - avec lui, vous obtiendriez le comportement que vous avez vu dans le shell Z.la source