En supposant que $file
détient la valeur dun nom de fichier, dites Dr" A.tif
. Dans la programmation bash, comment pourrais-je échapper aux guillemets simples et à tout autre caractère spécial de $file
sans supprimer le caractère spécial?
Mise à jour du 9 juillet 2014
Comme demande de @Gilles , extrait de code suivant qui « ne peut pas gérer Dr" A.tif
:
files=$(find /path/ -maxdepth 1 -name "*.[Pp][Dd][Ff]" -o -name "*.[Tt][Ii][Ff]") echo "${files}" > ${TEMP_FILE} while read file do newfile=$(echo "${file}" | sed "s, ,\\ ,g") ## line 1 done < ${TEMP_FILE}
Après avoir essayé le réponse de @Patrick sur line 1
, cela semble fonctionner pour moi. Mais si jai un fichier tel que Dr\^s A.tif
, la commande printf
ne semble pas aider, elle me montre Dr\^s\ A.tif
. Si je l’essaye manuellement sur console comme ceci:
printf "%q" "Dr\^s A.tif"
Jaurai cette sortie:
Dr\\\^s\ A.tif
Avez-vous une idée de comment gérer cela?
Commentaires
- dans quoi contexte prévoyez-vous dutiliser $ file? ou est-ce que ce problème affecte la chaîne avec le caractère spécial à $ file?
- En fait, la commande find me renvoie un tableau de liste de fichiers. Et puis je parcourt cette liste de fichiers dans la variable $ file.
- Vous ' avez reçu des réponses correctes ici, mais ce ne sont probablement pas les réponses à la question que vous ' posez vraiment. Daprès votre commentaire, je soupçonne fortement que vous ' êtes sur la mauvaise voie. Nous pouvons ' t vous aider beaucoup parce que vous continuez de ne pas afficher votre code. Je vous recommande cependant de lire Pourquoi mon script shell sétouffe-t-il avec des espaces ou dautres caractères spéciaux? en arrière-plan. Montrez votre script et expliquez ce que vous voulez faire.
Réponse
Vous peut utiliser le printf
intégré avec %q
pour accomplir cela. Par exemple:
$ file="Dr" A.tif" $ printf "%q\n" "$file" Dr\"\ A.tif $ file=" foo$bar\baz`" $ printf "%q\n" "$file" \ foo\$bar\\baz\`
De la documentation bash sur printf
:
In addition to the standard format specifications described in printf(1) and printf(3), printf interprets: %b expand backslash escape sequences in the corresponding argument %q quote the argument in a way that can be reused as shell input %(fmt)T output the date-time string resulting from using FMT as a format string for strftime(3)
Commentaires
- Ce ne fonctionne pas ' avec certains cas .eg lorsque vous devez conserver les guillemets doubles.
- @ user3467349 cela fonctionne très bien avec les guillemets. Je ' parie que vous ' essayez quelque chose comme
printf '%s' "foo"
. Vous devez dabord comprendre comment lanalyse des arguments fonctionne dans le shell. Voir gnu.org/software/bash/manual/bash.html#Shell-Operation # 2 se produit avant le # 6. - Pourriez-vous fournissez un exemple de cette chaîne imprimée avec
printf
et aucune autre manipulationIt doesn't have a: ""
- Votre problème na rien à voir avec
printf
. Votre problème est que vous ' ne voulez pas que le shell analyse votre chaîne. Pour ce faire, vous devez passer votre entrée au shell dune manière où il nessaye même pas de lanalyser. '. Une façon de procéder serait deread -r -p 'input: ' && printf '%q\n' "$REPLY"
, et de fournir lentrée lorsque vous y êtes invité. - Comme je ' ve dit plusieurs fois maintenant. Ne pas savoir comment transmettre des données brutes au shell nest ' t un problème avec
printf
. Vous devriez peut-être poser une question plutôt que critiquer une solution qui n’a rien à voir avec votre problème.
Réponse
Essayez: –
file=Dr\"\ A.tif echo $file Dr" A.tif
ou
file="Dr" A.tif" echo $file Dr" A.tif
ou si la chaîne contient un double quote: –
file="Dr" A.tif" echo $file Dr" A.tif
Il existe de bons tutoriels sur les échappements et les citations sur le net. Commencez par celui-ci .
Réponse
Vous ne « Vous navez pas besoin déchapper aux noms de fichiers que vous manipulez dans un script. Léchappement nest nécessaire que si vous voulez mettre un nom de fichier comme littéral dans un script, ou pour passer plusieurs noms de fichiers en un seul flux dentrée vers un autre script.
Étant donné que vous « bouclez sur la sortie de find
, ceci est lun des moyens les plus simples (!) de gérer tous les chemins possibles :
while IFS= read -r -d "" do file_namex="$(basename -- "$REPLY"; echo x)" file_name="${file_namex%$"\nx"}" do_something -- "$file_name" done <(find "$some_path" -exec printf "%s\0" {} +)
Réponse
rapide et (très) sale
find . | sed "s/^/"/" | sed "s/$/"/"
Réponse
Beaucoup de ces réponses, y compris la réponse la plus votée en utilisant printf "%q"
ne fonctionne pas dans tous les cas sans manipulation supplémentaire.Je suggérerais ce qui suit (exemple ci-dessous):
cat <<EOF; 2015-11-07T03:34:41Z app[postgres.0000]: [TAG] text-search query doesn"t contain lexemes: "" EOF
Commentaires
- Excusez la question n00b, mais pouvez-vous expliquer comment vous utiliseriez réellement cela pour échapper des caractères dans une chaîne? Si je copie le code que vous écrivez dans mon terminal, il imprime simplement 2015-11-07T03: 34: 41Z app [postgres.0000]: [TAG] la requête de recherche de texte ne ' t contiennent des lexèmes: " " … rien nest échappé.
- Que ' est littéralement le point, tous les caractères spéciaux sont interprétés comme des caractères littéraux et non pour leur signification particulière. Essayez plutôt de faire écho " la chaîne ci-dessus " pour voir la différence.