Question Comment faire pour échapper des guillemets simples dans les guillemets simples?


Disons que vous avez un bash alias comme:

alias rxvt='urxvt'

ce qui fonctionne bien.

Toutefois:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

ne fonctionnera pas, et ne le fera pas non plus:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

Alors, comment finissez-vous par faire correspondre les guillemets d'ouverture et de fermeture dans une chaîne une fois que vous avez échappé des citations?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

semble disgracieux bien qu'il représenterait la même chaîne si vous êtes autorisé à les concaténer comme ça.


724
2017-08-08 22:50


origine


Réponses:


Si vous voulez vraiment utiliser des guillemets simples dans la couche la plus externe, rappelez-vous que vous pouvez coller les deux types de citation. Exemple:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

Explication de comment '"'"' est interprété comme juste ':

  1. ' Terminez la première citation qui utilise des guillemets simples.
  2. " Commencez la deuxième citation, en utilisant des guillemets doubles.
  3. ' Caractère cité.
  4. " Terminez la deuxième citation en utilisant des guillemets.
  5. ' Commencer la troisième citation, en utilisant des guillemets simples.

Si vous ne placez aucun espace entre (1) et (2), ou entre (4) et (5), le shell interprétera cette chaîne comme un long mot.


1067
2017-08-09 00:52



Je remplace toujours chaque guillemet simple incorporé par la séquence: '\'' (c'est-à-dire: citation backslash citation de devis) qui ferme la chaîne, ajoute un guillemet simple échappé et rouvre la chaîne.


Je crée souvent une fonction "quotify" dans mes scripts Perl pour faire ça pour moi. Les étapes seraient:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

Cela prend à peu près tous les cas.

La vie devient plus amusante quand vous présentez eval dans vos scripts shell. Vous devez essentiellement tout re-citer encore!

Par exemple, créez un script Perl appelé quotify contenant les instructions ci-dessus:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

puis utilisez-le pour générer une chaîne correctement citée:

$ quotify
urxvt -fg '#111111' -bg '#111111'

résultat:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

qui peut ensuite être copié / collé dans la commande alias:

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(Si vous devez insérer la commande dans un eval, exécutez à nouveau le quotify:

 $ quotify
 alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

résultat:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

qui peut être copié / collé dans un eval:

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

196
2017-08-22 05:30



Depuis Bash 2,04 syntaxe $'string' (au lieu de simplement 'string'; avertissement: ne pas confondre avec $('string')) est un autre mécanisme de citation qui permet Séquences d'échappement ANSI C-like et faire l'expansion à la version à guillemets simples.

Exemple simple:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

Dans ton cas:

$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

Les séquences d'échappement communes fonctionnent comme prévu:

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

Vous trouverez ci-dessous la documentation relative à la copie et au collage de man bash (version 4.4):

Les mots de la forme $ 'chaîne' sont traités spécialement. Le mot se développe en chaîne, avec des caractères d'échappement à barre oblique inverse remplacés comme spécifié par la norme ANSI C. Les séquences d'échappement antislash, si présentes, sont décodées comme suit:

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal 
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
               is the hexadecimal value HHHHHHHH (one to eight 
               hex digits)
    \cx    a control-x character

Le résultat étendu est un guillemet simple, comme si le signe dollar n'avait pas été présent.


Voir Citations et échappement: chaînes de type ANSI C sur le wiki bash-hackers.org pour plus de détails. Notez également que "Changements de Bash" fichier (aperçu ici) mentionne beaucoup de changements et de corrections de bogues liés à $'string' mécanisme de citation.

Selon unix.stackexchange.com Comment utiliser un caractère spécial comme normal?cela devrait fonctionner (avec quelques variations) dans bash, zsh, mksh, ksh93 et ​​FreeBSD et busybox sh.


113
2018-05-17 08:56



Je ne vois pas l'entrée sur son blog (lien pls?) Mais selon le manuel de référence gnu:

Inclure des caractères dans des guillemets simples   ('' ') Préserve la valeur littérale de   chaque caractère dans les citations. UNE   une seule citation peut ne pas se produire entre   guillemets simples, même lorsqu'ils sont précédés d'un   antislash.

donc bash ne comprendra pas:

alias x='y \'z '

Cependant, vous pouvez le faire si vous entourez de guillemets doubles:

alias x="echo \'y "
> x
> 'y

42
2017-08-08 23:07



Je peux confirmer que l'utilisation '\'' car une seule citation à l'intérieur d'une chaîne entre guillemets fonctionne dans Bash, et elle peut être expliquée de la même manière que l'argument "collage" du début du fil. Supposons que nous ayons une chaîne entre guillemets: 'A '\''B'\'' C' (Toutes les citations sont des guillemets simples). Si elle est passée à l'écho, elle imprime ce qui suit: A 'B' C. Dans chaque '\'' la première citation ferme la chaîne de guillemets simples actuelle, la suivante \' colle une seule citation à la chaîne précédente (\' est un moyen de spécifier une seule citation sans démarrer une chaîne entre guillemets), et la dernière citation ouvre une autre chaîne entre guillemets simples.


26
2017-08-03 07:54



Exemple simple d'échappement de guillemets dans le shell:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

C'est fait en terminant un déjà ouvert ('), plaçant un échappé (\'), puis en ouvrant un autre ('). Cette syntaxe fonctionne pour toutes les commandes. C'est une approche très similaire à la première réponse.


14
2018-02-28 20:59



Je ne parle pas spécifiquement de la question des citations parce que, parfois, il est juste raisonnable d'envisager une autre approche.

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

que vous pouvez ensuite appeler comme:

rxvt 123456 654321

l'idée étant que vous pouvez maintenant alias ceci sans souci de guillemets:

alias rxvt='rxvt 123456 654321'

ou, si vous devez inclure le # dans tous les appels pour une raison quelconque:

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

que vous pouvez ensuite appeler comme:

rxvt '#123456' '#654321'

alors, bien sûr, un alias est:

alias rxvt="rxvt '#123456' '#654321'"

(Oups, je suppose que j'ai un peu abordé la citation :)


11
2017-08-22 04:59