51 votes

Utiliser sed sur une variable de type chaîne de caractères plutôt que sur un fichier

On m'a dit qu'il était possible, mais sans un seul exemple concret, que sed peut lire une variable de type chaîne de caractères sans avoir besoin d'un fichier d'entrée. Je n'ai pas encore réussi à le faire fonctionner. Pour des raisons de sécurité, j'écris le programme $PATH à une autre variable, car je ne veux pas que d'autres problèmes surgissent tant que je ne sais pas exactement comment faire.

Considérez ce qui suit :

~$x=$PATH
~$sed -i 's/:/ /g' $x

cela échoue avec : No such file or directory.

En voici d'autres que j'ai essayés :

~$ sed -i 's/:/ /g' | (read x) 
sed: no input files
~$ sed -i 's/:/ /g' | (read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' | $(read x) 
sed: no input files
~$ sed -i 's/:/ /g' | $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
sed: no input files
~$ sed -i 's/:/ /g' < $(read $x) 
bash: read: `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games': not a valid identifier
bash: $(read $x): ambiguous redirect
~$ sed -i 's/:/ /g' < read $x 
bash: read: No such file or directory
~$ sed -i 's/:/ /g' < (read x) 
bash: syntax error near unexpected token `('
~$ sed -i 's/:/ /g' < $((read x)) 
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: syntax error: operand expected (error token is "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' < $((read $x)) 
bash: read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: division by 0 (error token is "usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games")
~$ sed -i 's/:/ /g' << $((read $x)) 
> ;^C
~$ sed -i 's/:/ /g' << $(read $x)
> ;^C
~$ sed -i 's/:/ /g' $x
sed: can't read /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < $x
bash: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games: No such file or directory
~$ sed -i 's/:/ /g' < echo $x
bash: echo: No such file or directory
~$ sed -i 's/:/ /g' |  echo $x
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
sed: no input files

Est-ce que cela peut fonctionner ? Je préférerais ne pas avoir à écrire des fichiers dont je n'ai pas besoin juste pour pouvoir utiliser sed. Pour cet exemple particulier, si ~$x=$PATH ~$sed -i 's/:/ /g' $x a réellement fonctionné comme je l'espérais, je l'obtiendrais :

/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games

que je pourrais ensuite assigner à une variable et utiliser dans des commandes ultérieures, telles que ls $x

51voto

Stewart Points 1385

Cela n'a rien à voir avec sed en tant que tel, il s'applique à tout programme qui lit l'entrée standard. Quoi qu'il en soit, ce que vous recherchez est

sed 's/:/ /g' <<<"$PATH"

Il n'y a aucune raison de sauvegarder dans une autre variable, rien de ce que vous faites de cette façon n'affectera la valeur stockée dans la variable. Vous avez besoin de l'opérateur d'affectation ( = ). La syntaxe utilisée ci-dessus est appelée "ici chaîne" et est spécifique à bash, ksh et zsh. Il sert à transmettre la valeur d'une variable comme entrée à un programme qui lit à partir de l'entrée standard.

J'ai rédigé une réponse sur l'U&L qui répertorie tous les opérateurs Shell comme celui-ci. Vous pouvez y jeter un coup d'œil.

Notez que vous auriez également pu faire

echo "$PATH" | sed 's/:/ /g' 

Enfin, vous n'avez pas besoin de sed pour cela. Vous pouvez faire tout cela en bash directement :

echo "${PATH//:/ }"

Ce qui précède est une construction de remplacement de bash. Étant donné une variable $var , un modèle pat et un remplacement ( rep ), pour remplacer toutes les occurrences de pat avec rep vous feriez

echo "${var//pat/rep}"

La même chose avec une barre oblique simple ne remplace que la première occurrence :

echo "${var/pat/rep}"

28voto

bolichep Points 408

Peut-être :

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X