Disons que vous avez un Bash alias
comme:
alias rxvt='urxvt'
qui fonctionne bien.
Toutefois:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
ne fonctionnera pas, et non plus:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
Alors, comment finissez-vous par faire correspondre les guillemets d'ouverture et de fermeture à l'intérieur d'une chaîne une fois que vous avez échappé les guillemets?
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.
"\""
donc ceux-ci doivent être utilisés de préférence à la réponse de @ liori dans la mesure du possible.Réponses:
Si vous voulez vraiment utiliser des guillemets simples dans la couche la plus externe, n'oubliez pas que vous pouvez coller les deux types de devis. Exemple:
Explication de la façon dont
'"'"'
est interprété simplement'
:'
Fin de la première citation qui utilise des guillemets simples."
Commencez la deuxième citation en utilisant des guillemets doubles.'
Caractère cité."
Terminez la deuxième citation en utilisant des guillemets doubles.'
Commencez le troisième devis 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 seul mot long.
la source
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"
Cela fonctionne quand il y a des guillemets simples et des guillemets doubles dans la chaîne d'alias!alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
'\''
c'est beaucoup plus lisible dans la plupart des contextes que'"'"'
. En fait, le premier est presque toujours clairement distinct dans une chaîne entre guillemets simples, et il s'agit donc simplement de le mapper sémantiquement au sens "c'est une citation échappée", comme on le fait\"
dans les chaînes entre guillemets doubles. Alors que ce dernier se fond dans une seule ligne de cotations et nécessite une inspection minutieuse dans de nombreux cas pour bien distinguer.Je remplace toujours chaque guillemet simple incorporé par la séquence:
'\''
(c'est-à-dire guillemet entre guillemets) 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 le faire pour moi. Les étapes seraient les suivantes:
Cela s'occupe à peu près de tous les cas.
La vie devient plus amusante lorsque vous introduisez
eval
dans vos scripts shell. Vous devez essentiellement tout re-citer à nouveau!Par exemple, créez un script Perl appelé quotify contenant les instructions ci-dessus:
puis utilisez-le pour générer une chaîne correctement citée:
résultat:
qui peut ensuite être copié / collé dans la commande alias:
(Si vous devez insérer la commande dans un eval, exécutez à nouveau le guillemet:
résultat:
qui peut être copié / collé dans un eval:
la source
set -x
etecho "here's a string"
et vous verrez que bash s'exécuteecho 'here'\''s a string'
. (set +x
pour revenir à un comportement normal)Depuis la syntaxe Bash 2.04
$'string'
(au lieu de juste'string'
; avertissement: ne pas confondre avec$('string')
) est un autre mécanisme de citation qui permet des séquences d'échappement de type C ANSI et fait une expansion vers une version entre guillemets simples.Exemple simple:
Dans ton cas:
Les séquences d'échappement courantes fonctionnent comme prévu:
Vous trouverez ci-dessous la documentation relative à la copie et au collage de
man bash
(version 4.4):Les mots de la forme $ 'string' sont traités spécialement. Le mot se développe en chaîne, avec des caractères d'échappement antislash remplacés comme spécifié par la norme C ANSI. Les séquences d'échappement de barre oblique inverse, si elles sont présentes, sont décodées comme suit:
Le résultat étendu est guillemet simple, comme si le signe dollar n'était pas présent.
Voir Quotes and escape: ANSI C like strings sur bash-hackers.org wiki pour plus de détails. Notez également que le fichier "Bash Changes" ( aperçu ici ) mentionne beaucoup de changements et de corrections de bogues liés au
$'string'
mécanisme de cotation.D'après unix.stackexchange.com Comment utiliser un caractère spécial comme un caractère normal? cela devrait fonctionner (avec quelques variantes) dans bash, zsh, mksh, ksh93 et FreeBSD et busybox sh.
la source
echo $'foo\'b!ar'
=>!ar': event not found
> echo $BASH_VERSION
4.2.47(1)-release
> echo $'foo\'b!ar'
foo'b!ar
$'
façon la plus simple de l'essayer vous-même sur les anciens systèmes.e. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions.
Tiré de tiswww.case.edu/php/chet/bash/CHANGES . Fonctionne toujours en 4.3.42 mais pas en 4.3.48.Je ne vois pas l'entrée sur son blog (lien pls?) Mais selon le manuel de référence gnu :
donc bash ne comprendra pas:
alias x='y \'z '
cependant, vous pouvez le faire si vous entourez de guillemets doubles:
la source
Je peux confirmer que l'utilisation
'\''
d'un guillemet simple à l'intérieur d'une chaîne entre guillemets fonctionne dans Bash, et cela peut être expliqué de la même manière que l'argument "collage" plus haut dans le fil. Supposons que nous ayons une chaîne entre guillemets:'A '\''B'\'' C'
(toutes les guillemets ici sont des guillemets simples). Si elle est passée à l' écho, il imprime ce qui suit:A 'B' C
. Dans chacun,'\''
le premier guillemet ferme la chaîne entre guillemets actuelle, ce qui suit\'
colle un guillemet simple à la chaîne précédente (\'
est un moyen de spécifier un guillemet simple sans démarrer une chaîne entre guillemets), et le dernier guillemet ouvre une autre chaîne entre guillemets simples.la source
alias something='A '\''B'\'' C'
traduit parsomething
être une seule chaîne, donc même si le côté droit de l'affectation n'est pas techniquement une seule chaîne, je ne pense pas que cela ait beaucoup d'importance.'A ' + ' + 'B' + ' + ' C'
. En d'autres termes, une solution pour insérer des guillemets simples dans une chaîne entre guillemets devrait me permettre de créer une telle chaîne par elle-même et de l'imprimer. Cependant, cette solution ne fonctionnera pas dans ce cas.STR='\''; echo $STR
. Tel que conçu, BASH ne le permet pas vraiment.'\''
fonctionne pour bash. Pourriez-vous indiquer quelles sections de gnu.org/software/bash/manual/bashref.html spécifient un tel comportement?Les deux versions fonctionnent, soit avec concaténation en utilisant le caractère guillemet simple échappé (\ '), soit avec concaténation en enfermant le caractère guillemet simple entre guillemets doubles ("" ").
L'auteur de la question n'a pas remarqué qu'il y avait une citation supplémentaire (') à la fin de sa dernière tentative d'évasion:
Comme vous pouvez le voir dans la belle œuvre d'art ASCII / Unicode précédente, le dernier guillemet simple échappé (\ ') est suivi d'un guillemet simple inutile ('). L'utilisation d'un surligneur de syntaxe comme celui présent dans Notepad ++ peut s'avérer très utile.
Il en va de même pour un autre exemple comme le suivant:
Ces deux belles instances d'alias montrent de manière très complexe et obscurcie comment un fichier peut être aligné. Autrement dit, à partir d'un fichier avec beaucoup de lignes, vous obtenez une seule ligne avec des virgules et des espaces entre le contenu des lignes précédentes. Afin de donner un sens au commentaire précédent, voici un exemple:
la source
Exemple simple d'échapper des citations dans le shell:
Cela se fait en terminant un (
'
) déjà ouvert , en plaçant un (\'
) échappé , puis en ouvrant un autre ('
). Cette syntaxe fonctionne pour toutes les commandes. C'est une approche très similaire à la 1ère réponse.la source
Je n'aborde pas spécifiquement la question des citations parce que, parfois, il est tout simplement raisonnable d'envisager une approche alternative.
que vous pouvez ensuite appeler comme:
l'idée étant que vous pouvez maintenant alias cela sans souci de guillemets:
ou, si vous devez inclure le
#
dans tous les appels pour une raison quelconque:que vous pouvez ensuite appeler comme:
alors, bien sûr, un alias est:
(oups, je suppose que j'ai en quelque sorte abordé la citation :)
la source
Puisqu'on ne peut pas mettre de guillemets simples dans des chaînes entre guillemets simples, l'option la plus simple et la plus lisible est d'utiliser une chaîne HEREDOC
Dans le code ci-dessus, le HEREDOC est envoyé à la
cat
commande et la sortie de celui-ci est affectée à une variable via la notation de substitution de commande$(..)
Il est nécessaire de mettre une seule citation autour du HEREDOC car il se
$()
la source
dash
qui est le shell par défaut dans les scripts Ubuntu upstart et ailleurs.J'utilise simplement des codes shell .. par exemple
\x27
ou\\x22
selon le cas. Pas de soucis, jamais vraiment.la source
x27
(sur Centos 6.6)La plupart de ces réponses concernent le cas spécifique dont vous parlez. Il y a une approche générale qu'un ami et moi avons développé qui permet arbitraire de citer dans le cas où vous avez besoin de citer bash commandes à travers plusieurs couches d'expansion de la coquille, par exemple, par le biais de ssh,
su -c
,bash -c
, etc. Il y a un noyau vous primitif besoin, ici en bash natif:Cela fait exactement ce qu'il dit: il cite chaque argument individuellement (après l'expansion bash, bien sûr):
Cela fait la chose évidente pour une couche d'expansion:
(Notez que les guillemets autour
$(quote_args ...)
sont nécessaires pour transformer le résultat en un seul argumentbash -c
.) Et il peut être utilisé plus généralement pour citer correctement à travers plusieurs couches d'expansion:L'exemple ci-dessus:
quote_args
individuellement, puis combine la sortie résultante en un seul argument avec les doubles guillemets intérieurs.bash
,-c
et le résultat déjà cité une fois de l'étape 1, puis combine le résultat en un seul argument avec les doubles guillemets externes.bash -c
.C'est l'idée en un mot. Vous pouvez faire des choses assez compliquées avec cela, mais vous devez faire attention à l'ordre d'évaluation et aux sous-chaînes qui sont citées. Par exemple, ce qui suit fait les mauvaises choses (pour une définition de «mauvais»):
Dans le premier exemple, bash se développe immédiatement
quote_args cd /; pwd 1>&2
en deux commandes distinctesquote_args cd /
etpwd 1>&2
, par conséquent, le CWD est toujours/tmp
lorsque lapwd
commande est exécutée. Le deuxième exemple illustre un problème similaire pour la globalisation. En effet, le même problème de base se produit avec toutes les extensions bash. Le problème ici est qu'une substitution de commande n'est pas un appel de fonction: elle évalue littéralement un script bash et utilise sa sortie dans le cadre d'un autre script bash.Si vous essayez d'échapper simplement aux opérateurs shell, vous échouerez car la chaîne résultante transmise à
bash -c
n'est qu'une séquence de chaînes entre guillemets individuels qui ne sont alors pas interprétées comme des opérateurs, ce qui est facile à voir si vous faites écho à la chaîne qui ont été passés à bash:Le problème ici est que vous surestimez. Ce dont vous avez besoin, c'est que les opérateurs ne soient pas entre guillemets en entrée du boîtier
bash -c
, ce qui signifie qu'ils doivent être en dehors de la$(quote_args ...)
substitution de commande.Par conséquent, ce que vous devez faire dans le sens le plus général est de citer chaque mot de la commande non destiné à être développé au moment de la substitution de commande séparément, et de n'appliquer aucune citation supplémentaire aux opérateurs du shell:
Une fois que vous avez fait cela, la chaîne entière est un jeu équitable pour continuer à citer des niveaux d'évaluation arbitraires:
etc.
Ces exemples peuvent sembler surmené étant donné que des mots comme
success
,sbin
etpwd
ne doivent pas nécessairement être cité shell, mais le point essentiel à retenir lors de l' écriture d' un script prenant entrée arbitraire est que vous voulez citer tout ce que vous n'êtes pas absolument sûr doesn » t ont besoin de citer, parce que vous ne savez jamais quand un utilisateur va jeter dans unRobert'; rm -rf /
.Pour mieux comprendre ce qui se passe sous les couvertures, vous pouvez jouer avec deux petites fonctions d'aide:
qui énumérera chaque argument d'une commande avant de l'exécuter:
la source
vagrant ssh -c {single-arg} guest
. Le{single-arg}
doit être traité comme un seul argument car vagabond prend l'argument suivant après comme nom d'invité. La commande ne peut pas être modifiée. Mais j'avais besoin de passer une commande et ses arguments à l'intérieur{single-arg}
. Donc , je vousquote_args()
cite la commande et ses arguments, et de mettre des guillemets doubles autour du résultat, et cela a fonctionné comme un charme:vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest
. Merci!!!À mon humble avis, la vraie réponse est que vous ne pouvez pas échapper aux guillemets simples dans les chaînes entre guillemets simples.
C'est impossible.
Si nous supposons que nous utilisons bash.
Du manuel bash ...
Vous devez utiliser l'un des autres mécanismes d'échappement de chaîne "ou \
Il n'y a rien de magique
alias
qui exige qu'il utilise des guillemets simples.Les deux travaux suivants dans bash.
Ce dernier utilise \ pour échapper au caractère espace.
# 111111 n'a rien de magique non plus qui nécessite des guillemets simples.
Les options suivantes permettent d'obtenir le même résultat que les deux autres options, en ce que l'alias rxvt fonctionne comme prévu.
Vous pouvez également échapper directement au # gênant
la source
Dans l'exemple donné, utilisez simplement des guillemets doubles au lieu de guillemets simples comme mécanisme d'échappement externe:
Cette approche convient à de nombreux cas où vous souhaitez simplement passer une chaîne fixe à une commande: vérifiez simplement comment le shell interprétera la chaîne entre guillemets doubles à travers un
echo
, et échappez les caractères avec barre oblique inverse si nécessaire.Dans l'exemple, vous verriez que les guillemets doubles sont suffisants pour protéger la chaîne:
la source
De toute évidence, il serait plus facile de simplement entourer de guillemets doubles, mais quel est le défi à cela? Voici la réponse en utilisant uniquement des guillemets simples. J'utilise une variable au lieu de
alias
c'est donc plus facile à imprimer pour la preuve, mais c'est la même chose que d'utiliseralias
.Explication
La clé est que vous pouvez fermer le devis unique et le rouvrir autant de fois que vous le souhaitez. Par exemple,
foo='a''b'
c'est la même chose quefoo='ab'
. Vous pouvez donc fermer le guillemet simple, ajouter un guillemet simple littéral\'
, puis rouvrir le guillemet simple suivant.Diagramme de répartition
Ce diagramme le montre clairement en utilisant des crochets pour montrer où les guillemets simples sont ouverts et fermés. Les citations ne sont pas "imbriquées" comme peuvent l'être les parenthèses. Vous pouvez également faire attention à la surbrillance des couleurs, qui est correctement appliquée. Les cordes citées sont marron, tandis que le
\'
noir est.(Il s'agit essentiellement de la même réponse que celle d'Adrian, mais je pense que cela l'explique mieux. De plus, sa réponse contient 2 guillemets simples superflus à la fin.)
la source
'\''
méthode que je recommande par rapport à la'"'"'
méthode qui est souvent plus difficile à lire pour les humains.Voici une élaboration sur The One True Answer référencée ci-dessus:
Parfois, je téléchargerai en utilisant rsync sur ssh et je devrai échapper un nom de fichier avec un 'TWICE! (OMG!) Une fois pour bash et une fois pour ssh. Le même principe d'alternance des délimiteurs de devis est à l'œuvre ici.
Par exemple, disons que nous voulons obtenir: Les histoires de Louis Theroux ...
Et voici! Vous vous retrouvez avec ceci:
ce qui représente énormément de travail pour un tout petit - mais voilà
la source
Explication de la mise en œuvre:
guillemets doubles afin que nous puissions facilement sortir des guillemets simples et utiliser la
${...}
syntaxeLa recherche et le remplacement de bash ressemblent à ceci:
${varname//search/replacement}
nous remplaçons
'
par'\''
'\''
encode un single'
comme ceci:'
termine la citation unique\'
code un'
(la barre oblique inverse est nécessaire car nous ne sommes pas entre guillemets)'
recommence le guillemet simplebash concatène automatiquement les chaînes sans espace blanc entre
il y a un
\
avant chaque\
et'
parce que ce sont les règles d'échappement pour${...//.../...}
.PS Encode toujours les chaînes entre guillemets simples car elles sont bien plus simples que les chaînes entre guillemets doubles.
la source
Une autre façon de résoudre le problème de trop de couches de devis imbriqués:
Vous essayez de trop entasser dans un espace trop petit, utilisez donc une fonction bash.
Le problème est que vous essayez d'avoir trop de niveaux d'imbrication et que la technologie d'alias de base n'est pas assez puissante pour s'adapter. Utilisez une fonction bash comme celle-ci pour que les guillemets simples et doubles et les paramètres passés soient tous traités normalement comme nous nous y attendrions:
Ensuite, vous pouvez utiliser vos variables $ 1 et $ 2 ainsi que les guillemets simples, doubles et les ticks arrière sans vous soucier de la fonction d'alias qui détruit leur intégrité.
Ce programme imprime:
la source
Si GNU Parallel est installé, vous pouvez utiliser sa citation interne:
Depuis la version 20190222, vous pouvez même
--shellquote
plusieurs fois:Il cite la chaîne dans tous les shells pris en charge (pas seulement
bash
).la source
Cette fonction:
permet de citer l'
'
intérieur'
. Utilisez comme ceci:Si la ligne à citer devient plus complexe, comme les guillemets doubles mélangés à des guillemets simples, il peut devenir assez difficile d'obtenir la chaîne à citer dans une variable. Lorsque de tels cas apparaissent, écrivez la ligne exacte que vous devez citer dans un script (similaire à ceci).
Sortira:
Toutes les chaînes correctement citées dans des guillemets simples.
la source
Si vous générez la chaîne shell dans Python 2 ou Python 3, les éléments suivants peuvent aider à citer les arguments:
Cela produira:
la source
Voici mes deux cents - dans le cas où l'on veut être
sh
-portable, pas seulement-bash
spécifique (la solution n'est cependant pas trop efficace, car elle démarre un programme externe -sed
):quote.sh
(ou justequote
) quelque part sur votrePATH
:Un exemple:
Et, bien sûr, cela se reconvertit:
Explication: fondamentalement, nous devons entourer l'entrée de guillemets
'
, puis remplacer également toute guillemet simple à l'intérieur par ce micro-monstre:'"'"'
(terminer la guillemet d'ouverture par un appariement'
, échapper à la guillemet simple trouvé en l'enveloppant avec des guillemets doubles -"'"
, et puis enfin émettre un nouveau devis unique d'ouverture'
, ou pseudo-notation:' + "'" + ' == '"'"'
)Une façon standard de le faire serait d'utiliser
sed
la commande de substitution suivante:Un petit problème, cependant, est que pour utiliser cela dans le shell, il faut échapper à tous ces caractères de guillemet simple dans l'expression sed elle-même - ce qui conduit à quelque chose comme
(et une bonne façon de construire ce résultat est d'alimenter l'expression originale
s/\(['][']*\)/'"\1"'/g
des scripts de Kyle Rose ou de George V. Reilly).Enfin, il est logique de s'attendre à ce que l'entrée provienne
stdin
- car la passer à travers des arguments de ligne de commande pourrait déjà être trop difficile.(Oh, et peut-être que nous voulons ajouter un petit message d'aide afin que le script ne se bloque pas lorsque quelqu'un l'exécute simplement en se
./quote.sh --help
demandant ce qu'il fait.)la source
Voici une autre solution. Cette fonction prendra un seul argument et le citera de manière appropriée en utilisant le caractère de guillemet simple, comme l'explique la réponse votée ci-dessus:
Vous pouvez donc l'utiliser de cette façon:
la source