La préservation de devis en bash les paramètres de la fonction
Ce que je voudrais faire est de prendre comme entrée d'une fonction, d'une ligne qui peut inclure des guillemets (simples ou doubles) et l'écho de cette ligne exactement comme c'était prévu à la fonction. Par exemple:
function doit {
printf "%s " ${@}
eval "${@}"
printf " # [%3d]\n" ${?}
}
Qui, compte tenu de la manière suivante
doit VAR=42
doit echo 'single quote $VAR'
doit echo "double quote $VAR"
Les rendements suivants:
VAR=42 # [ 0]
echo single quote $VAR # [ 0]
echo double quote 42 # [ 0]
Si la sémantique de l'expansion des variables sont conservées en tant que je m'attends, mais je ne peux pas obtenir le format exact de la ligne, comme c'était prévu à la fonction. Ce que j'aimerais c'est avoir doit echo 'single quote $VAR'
résultat dans echo 'single quote $VAR'
.
Je suis sûr que cela a à voir avec bash de traiter les arguments avant qu'ils sont passés à la fonction; je suis à la recherche d'un moyen de contourner cela (si possible).
Modifier
Donc ce que j'avais prévu était de l'ombre à l'exécution d'un script, tout en fournissant une réplique exacte de l'exécution qui peut être utilisé comme un outil de diagnostic, y compris la sortie de l'état de chaque étape.
Alors que je peut obtenir le comportement souhaité décrit ci-dessus en faisant quelque chose comme
while read line ; do
doit ${line}
done < ${INPUT}
Cette approche échoue face à des structures de contrôle (c'est à dire if
, while
, etc). J'ai pensé à utiliser set -x
mais qui a ses limites: "
devient '
et de statut de sortie n'est pas visible pour les commandes qui ne.
OriginalL'auteur ezpz | 2010-07-15
Vous devez vous connecter pour publier un commentaire.
La raison à cela est parce que bash interprète les arguments, comme vous le pensiez. Les guillemets ne sont tout simplement pas plus lors de l'appel à la fonction, donc ce n'est pas possible. Il a travaillé dans le DOS parce que les programmes pourraient interpréter la ligne de commande eux-mêmes, non pas que cela vous aide!
OriginalL'auteur
J'ai été dans la même situation que vous, j'ai besoin d'un script pour l'enrouler autour d'une commande existante et de passer des arguments en préservant citant.
Je suis venu avec quelque chose qui ne préserve pas de la ligne de commande exactement comme entrée, mais ne passer les arguments correctement et de vous montrer ce qu'ils étaient.
Voici mon script mis en place pour l'ombre
ls
:Et ceci est un extrait de sortie:
Donc, comme vous pouvez le voir, il ajoute des guillemets qui n'étaient pas là à l'origine, mais il ne conserver arguments avec des espaces dans lesquels est ce dont j'avais besoin.
OriginalL'auteur
Bien que @Pierre Westlakerépondre est correct, et il n'y a pas de citations pour préserver l'on peut tenter d'en déduire si les citations, si nécessaire et ainsi se passa dans l'origine. Personnellement j'ai utilisé cette
requote
fonction lorsque j'avais besoin d'une preuve dans les journaux qu'une commande est exécutée avec le bon de citer:Et voici comment je l'utilise:
$'\'"$(rm -rf $HOME)"\''
. Aussi,$(foo)
ne contient pas d'espaces, mais il doit encore être cité pour être sûr.Bien mieux serait d'utiliser
printf %q
, dont la coque garantit va générereval
la sortie sans danger.Aussi,
printf '%s\n' "${res# }"
est une façon beaucoup plus efficace de faire de la suppression de la première de l'espace-et-print chose. Et[[ $x = *[[:space:]]* ]]
est une façon beaucoup plus efficace pour vérifier si une variable contient des espaces.OriginalL'auteur
Les deux fonctionneront.
bash ne bande de l'extérieur ensemble de citations lors de la saisie de la fonction.
C'était la réponse dont j'avais besoin. Donc "$@" préserve les apostrophes dans la valeur de $@.
OriginalL'auteur
Bash va supprimer la citation lorsque vous passez d'une chaîne à citer comme argument de ligne de commande. La citation est tout simplement pas plus là quand la chaîne est en passe de votre script. Vous n'avez aucun moyen de savoir qu'il est un guillemet simple ou double quote.
Ce que vous pouvez probablement le faire est qqch comme ceci:
Dans votre script, vous obtenez
Ou faire
Dans votre script, vous obtenez
OriginalL'auteur
Ce:
Comme un exemple a des problèmes lorsque les paramètres ont des apostrophes.
Cette fonction:
résout le problème évoqué et vous pouvez utiliser les paramètres, y compris les apostrophes à l'intérieur, comme "Porky's", et renvoie, apparemment(?), la même chaîne de paramètres lors de chaque paramètre est cité; si non, il cite. Étonnamment, je ne comprends pas pourquoi, si vous l'utilisez de manière récursive, il ne renvoie pas la même liste, mais chaque paramètre est cité à nouveau. Mais si vous faire l'écho de chacun de vous permettre de récupérer le paramètre d'origine.
Exemple:
Et:
Et celui-ci:
retour à un niveau de citation de moins en moins,
cela ne fonctionne pas, ni en alternance à la fois de manière récursive.
OriginalL'auteur
Le shell va interpréter le devis et la
$
avant de le transmettre à votre fonction. Il n'y a pas beaucoup de fonction que vous pouvez faire pour obtenir les caractères spéciaux en arrière, car il n'a aucun moyen de savoir (dans le double-quote exemple) si42
a été codé en dur ou si il est venu à partir d'une variable. Vous avez pour échapper les caractères spéciaux si vous voulez survivre assez longtemps pour se rendre à votre fonction.OriginalL'auteur
Si la coque n'est pas en charge le modèle de substitution, c'est à dire
${param/pattern/string}
alors la suivantesed
expression peut être utilisée en toute sécurité de citer toute la chaîne de manière à ce qu'ileval
dans un seul paramètre nouveau:Combinant cela avec
printf
il est possible d'écrire une petite fonction qui va prendre toute la liste des chaînes produites par nom de fichier d'extension ou"$@"
et de le transformer en quelque chose qui peut être passé en toute sécurité àeval
pour la développer dans les arguments pour une autre commande tout en préservant paramètre de séparation.Il peut être plus facile (et peut-être plus sûr, c'est à dire éviter
eval
) dans certaines situations, l'utilisation d'un "impossible" de caractère comme le séparateur de champ, puis utilisezIFS
pour contrôler l'expansion de la valeur à nouveau.OriginalL'auteur