Existe-t-il un moyen d'échapper aux guillemets simples dans le shell?


11

Par exemple. je veux dire

perl -e 'print '"'"'Hello, world!'"'"', "\n";'

Y a-t-il une manière moins maladroite de le faire, par exemple en échappant aux guillemets simples?

Oui, je sais que je peux écrire

perl -e 'print q[Hello, world!], "\n"'
perl -e 'print "Hello, world!\n"'

Mais cette question concerne les citations dans le shell, pas dans le Perl.

Je suis intéressé à le faire dans bashet cshen premier lieu.

Réponses:


9

Dennis souligne les alternatives habituelles dans sa réponse (simple-en-double, double-en-simple, guillemets simples concaténés avec des guillemets simples échappés; vous avez déjà mentionné les opérateurs de devis personnalisables de Perl), mais c'est peut-être la réponse directe que vous cherchiez pour.

Dans les shells de type Bourne (sh, ksh, ash, dash, bash, zsh, etc.), les chaînes entre guillemets simples sont complètement littérales. Cela permet d'inclure facilement des caractères que le shell traiterait autrement sans avoir à les échapper, mais cela signifie que le caractère guillemet simple lui-même ne peut pas être inclus dans des chaînes entre guillemets simples.

Je refuse même de penser aux shells de type csh car ils sont complètement cassés à d'autres égards (voir la programmation Csh considérée comme nuisible ).


Je vous remercie. "C'est impossible" - c'est la réponse que j'attendais :) Bien que j'aie toujours espéré que ce sont ici des documents qui sont dédiés à jouer ce rôle.
codeholic

Contrairement à Perl, les documents shell de type Bourne ici ne sont directement utiles que pour fournir une entrée via stdin. Vous pouvez bien sûr y mettre des guillemets simples. Vous pouvez également activer le "mode littéral" d'un document ici en citant le mot: (par exemple) blah <<\EOF … EOF. Vous pouvez également utiliser <<'EOF'et <<"EOF. Ils signifient tous littéralement ici des documents (contrairement à Perl). Si vous étiez vraiment déterminé, vous pourriez le faire blah "$(cat<<\EOF … EOF )" other args(en utilisant des retours à la ligne où j'ai écrit des espaces dans la substitution de commande; ksh et zsh peuvent se passer du chat , les autres en ont besoin). Mais en vaudrait-il vraiment la peine?
Chris Johnsen

Je veux juste noter que les guillemets simples zsh ne sont pas tout à fait littéraux. Zsh essaiera d'interpréter un '\ U' n'importe où dans une chaîne entre guillemets simples comme un code de caractère, par exemple echo '\U0000068\U000069'fait écho à 'hi'. Je ne sais pas pourquoi, sauf si c'est un bug dans le shell.
Matthew

1
@Matthew: L'interprétation \Udans ce cas se fait par la commande echo intégrée (ce comportement peut être contrôlé par -Eou l'option BSD_ECHO et -e). Vous pouvez voir que la chaîne littérale est passée (et non interprétée autrement) dans d'autres commandes; par exemple printf %s\\n '\U0000068\U000069'.
Chris Johnsen

@ChrisJohnsen Merci, je suis nouveau sur zsh et je ne m'en étais pas rendu compte mais vous avez raison. La page de manuel m'a dit que -e est par défaut mais zsh doit le remplacer.
Matthew

5

Pour moi, tous vos exemples produisent:

Bonjour le monde!

Et cela aussi:

perl -e 'print "Hello, world!", "\n";'

Et ça:

perl -e 'print '\''Hello, world!'\'', "\n";'

Pouvez-vous clarifier ce que vous essayez de faire?

Dans le shell, comme Bash, si vous souhaitez imprimer des guillemets dans le cadre de la chaîne, un type de guillemets échappe à l'autre.

$ echo '"Hello, world!"'
"Hello, world!"
$ echo "'Hello, world!'"
'Hello, world!'

Éditer:

Voici une autre façon:

$ perl -e 'print "\047Hello, world!\047", "\n";'
'Hello, world!'
$ echo -e "\047Hello, world! \047"
'Hello, world! '

L'espace après le point d'exclamation évite une erreur d'extension d'historique. J'aurais pu faire à la set +Hplace.


1

Je ne sais pas si ma modification de la réponse précédente apparaîtra:

Coller la même chose qu'une nouvelle réponse:

Approche alternative:

Quand j'ai essayé votre solution, je n'ai toujours pas pu l'imprimer.

Mais je me suis inspiré de votre solution et j'ai essayé ce qui suit:

$ perl -e '$foo = chr(39); print "${foo}Hello, world ${foo}", "\n";'
'Hello, world '

La valeur ASCII de 'est 39.

J'en avais besoin pour effectuer une modification en ligne d'un tas de fichiers à ajouter «à un endroit d'intérêt.


1

Ici, le document est le meilleur moyen de ne pas se soucier de s'échapper:

$ cat <<EOF
my $var = "Hello";
print $text, ', world!', "\n";'
EOF

Vous pouvez interdire complètement toute expantion en utilisant le document cité ici:

$ cat <<'EOF'
my $var = "Hello";
print $text, ', world!', "\n";'
EOF

Si vous voulez le passer comme argument au lieu d'entrée, vous pouvez utiliser xargs:

$ xargs -0 <<'EOF' perl -e
my $var = "Hello";
print $text, ', world!', "\n";'
EOF

0

Je ne sais pas s'il existe une option pour le faire dans bash, mais avec zsh, vous pouvez l'utiliser ''après avoir activé l' RC_QUOTESoption. (Je recommanderais d'essayer zsh; il est principalement compatible avec bash et peut émuler bash pour encore plus de compatibilité.)

Avec bash (et toujours la plupart du temps avec zsh), je l'utilise simplement '\''parce qu'il est plus facile à lire que '"'"'.

Je n'ai absolument aucune idée de comment le faire dans csh.


-1

Vous pouvez utiliser \ 'et \ "pour échapper les guillemets avec perl s'ils sont utilisés en interne dans le cadre d'un script perl. Je ne sais pas si la ligne de commande acceptera cela. Vous pouvez l'essayer et voir si cela fonctionne.


3
Si c'était si facile, je ne demanderais pas. Vous pouvez l'essayer et voir si cela fonctionne avant de poster une réponse.
codeholic
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.