Pour ceux qui l'ignorent, en shell (et j'imagine que make fait dans le même genre) vous avez trois méthode d'échappement
* Le backslash qui échappe le caractère suivant : un\ nom\ complexe
* Les guillemets simples, 'un nom complexe'
* Les guillemets double, qui permettent l'interpolation de variable : "un $nom complexe"
Les choses se compliquent lorsque vous voulez faire du traitement par lot sur des fichiers qui peuvent potentiellement contenir des guillemets double ou simple. En effet, dans des scripts (propres), on utilisera des guillemets pour se prévenir des problèmes liés à d'autres caractères spéciaux (l'espace par exemple). Des guillemets simple peuvent contenir des guillemets double et inversement, mais si on à les deux dans un lot ou dans un seul fichier, cela ne fonctionne plus.
À priori un simple filtre qui échappe tous les caractères spéciaux avec un backslash devrait faire l'affaire.
N'ayant pas trouvé de filtre adéquate[2], je me suis donc un peu penché sur la question, et j'ai pondu le code (quick and dirty) suivant :
#!/usr/bin/perl
#?
sub escaped {
s/\\/\\\\/g; # backslash
s/\ /\\\ /g; # espace
s/\'/\\\'/g; # guillemet, etc.
s/\"/\\\"/g;
s/\(/\\\(/g;
s/\)/\\\)/g;
# Vous pouvez en ajouter d'autres bien sûr
return $_;
}
#? pour chaque ligne lue
while(<>){
#? Afficher le résultat de l'échappement sur la ligne courante
print escaped( $_);
}
Et son application :
% ls *.ex
file"with"quotes( and 'simple').ex
% ls *.ex|./escape.pl
file\"with\"quotes\(\ and\ \'simple\'\).ex
Seulement voila, si je fait un copier/coller du résultat, c'est bon, mais pas si je l'utilise directement:
#copié de ci-dessus
% cat file\"with\"quotes\(\ and\ \'simple\'\).ex
tada !
% cat $(ls *.ex|./escape.pl)
cat: file\"with\"quotes\(\: Aucun fichier ou dossier de ce type
cat: and\: Aucun fichier ou dossier de ce type
cat: \'simple\'\).ex: Aucun fichier ou dossier de ce type
Bon, visiblement il ne prends pas mon échappement d'espace et considère les espaces comme des séparateur d'arguments. Résultat assez inattendu puisqu'à priori il mange exactement la même chaîne de caractère qu'au dessus.
Voilà, à vos commentaires !
[1] http://linuxfr.org/~mildred/28576.html
[2] Il y avait bien http://search.cpan.org/dist/String-Escape/Escape.pm mais il n'échappe pas les guillemets simples.
# C'est pas utilie pour GNU ls
Posté par claudex . Évalué à 3.
Exemple:
$ touch t\'est
$ ls --quoting-style=shell
't'\''est'
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: C'est pas utilie pour GNU ls
Posté par psychoslave__ (site web personnel) . Évalué à 2.
escape $@ $+ | xargs $(GENPDF) -o
pour reprendre l'exemple du journal de mildred.
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 2.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 3.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: C'est pas utilie pour GNU ls
Posté par Mildred (site web personnel) . Évalué à 1.
[^] # Re: C'est pas utilie pour GNU ls
Posté par psychoslave__ (site web personnel) . Évalué à 2.
cible=$(echo $@|escape)
source=$(echo $+|escape)
echo $cible $source | xargs $(GENPDF) -o
La solution avec sed cité ci-dessus me paraît bien meilleur, sed à plus de chance d'être présent sur le système.
http://linuxfr.org/comments/1051999.html#1051999
[^] # Re: C'est pas utilie pour GNU ls
Posté par Moonz . Évalué à 2.
a\ ()'":
...cible=$(echo $+|escape)
...echo $$cible
$ make
cible=
echo $cible
$
# Où est le problème ?
Posté par Moonz . Évalué à 2.
a ()'"
$ cat "$(ls *)"
Hello, world
[^] # Re: Où est le problème ?
Posté par psychoslave__ (site web personnel) . Évalué à 2.
[^] # Re: Où est le problème ?
Posté par Moonz . Évalué à 2.
# IFS
Posté par tuXico . Évalué à 4.
Le ls va envoyer dans le pipe une ligne avec un espace qui sera interprété comme un séparateur.
(un truc du genre
OLDIFS=$IFS
IFS=$'\n'
ton cat
*puis*
IFS=$OLDIFS
devrait t'aider)
# Une réponse
Posté par FReEDoM (site web personnel) . Évalué à 1.
eval cat "`ls *.ex|./escape.pl`"
# simple quotes
Posté par Mildred (site web personnel) . Évalué à 1.
As you can see, FON did take some precautions to prevent people injecting code: Parameters are enclosed in single quotes to avoid substitutions of any kind. The entering of strange characters is prohibited by the web interface, and even if you manage to get a single quote character into your ESSID, it will be "defused" by prepending a backslash to it.
[...]
But wait, is it? I was quite surprised when I consulted the bash manual page:
"Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash."
Pour traduire la page de manuel:
Chaque caractère dans des simples quotes préserve son sens. Une simple quote ne peux pas être présente au milieu d'une chaîne de caractères délimitée par de simples quotes, même si elle est précédée par un antislash.
http://stefans.datenbruch.de/lafonera/
[^] # Re: simple quotes
Posté par psychoslave__ (site web personnel) . Évalué à 2.
[^] # Re: simple quotes
Posté par Vivi (site web personnel) . Évalué à 1.
Dans le langage de prog. que j'utilise quotidiennement, la fonction de bibliothèque qui fait cet échappement destiné au shell fonctionne comme ceci:
- la chaîne est mise entre simple quote
- les simple quotes à l'intérieur sont remplacées par '\''
par exemple:
abc"def'ghi
=> 'abc"def'\''ghi'
ça donne un truc simple et lisible quand y'a pas de ' dans la chaîne (et un moins lisible quand y'en a, certes)
[^] # Re: simple quotes
Posté par Mildred (site web personnel) . Évalué à 1.
' -> ' " ' " ' (sans les espaces)
ça donne:
abc"def'ghi -> 'abc"def'"'"'ghi'
mais ce que je voulais dire c'est que ce n'est pas comme on pourrait penser \'
# use String::ShellQuote;
Posté par rictus (site web personnel) . Évalué à 1.
??
use String::ShellQuote;
my $workdir = shell_quote($opt_workdir);
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.