Utilisez sed sur une variable chaîne plutôt que sur un fichier

30

On m'a dit que c'était possible, mais sans un seul exemple de travail, qui sedpeut lire à partir d'une variable de chaîne sans avoir besoin d'un fichier d'entrée. Je dois encore le faire fonctionner. Pour des raisons de sécurité générale, j'écris la $PATHvariable dans une autre variable, car je joue avec cela, car je n'ai pas besoin que d'autres problèmes surviennent jusqu'à ce que je sache exactement comment procéder.

Considérer ce qui suit:

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

cela échoue avec: Aucun fichier ou répertoire.

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

~$ 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

Cela peut-il même fonctionner? Je préférerais ne pas avoir à écrire des fichiers dont je n'ai pas besoin pour pouvoir utiliser sed. Pour cet exemple particulier, si cela ~$x=$PATH ~$sed -i 's/:/ /g' $xfonctionnait comme je l'aurais espéré, j'obtiendrais:

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

que je pourrais ensuite attribuer à une variable, et utiliser dans de futures commandes, comme ls $x

j0h
la source
1
x=$(echo "$x" | sed 's/:/ /g')?
heemayl

Réponses:

16

Peut être:

~$ x="$PATH"
~$ x="$(echo $x | sed 's/:/ /g')"
~$ echo "$x"
/usr/local/bin /usr/bin /bin /usr/local/games /usr/games
bolichep
la source
@jOh --- notez sedqu'ici ne fonctionne pas sur la "variable chaîne" (?), mais sur l'entrée standard --- ce qui devrait être ainsi.
Rmano
Je pense que je ferai une demande de fonctionnalité aux développeurs sed
j0h
4
@ j0h cela n'a rien à voir avec sed, il s'agit de savoir comment le shell redirige l'entrée. sedtraite les flux d'entrée et les lit via son entrée standard. Qu'il s'agisse de fichiers ou non n'a pas d'importance. Il peut accepter n'importe quoi tant qu'il provient d'une entrée standard.
terdon
38

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

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

Il n'y a aucune raison d'enregistrer 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 ( =) pour cela. La syntaxe utilisée ci-dessus est appelée "chaîne ici" et est spécifique à bash, ksh et zsh. Il sert à transmettre la valeur d'une variable en entrée à un programme qui lit à partir de l'entrée standard.

J'ai rédigé une réponse sur U&L qui répertorie tous les différents opérateurs de shell comme celui-ci. Vous voudrez peut-être y jeter un œil.

Notez que vous auriez pu aussi faire

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

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

echo "${PATH//:/ }"

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

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

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

echo "${var/pat/rep}"
terdon
la source
2
Merci pour la «construction de remplacement bash». J'ai pu utiliser: "$ {1 / from / to}" dans une fonction Bash pour modifier le premier argument dans les paramètres suivants.
AAAfarmclub