web-dev-qa-db-fra.com

Substitution variable d'environnement dans sed

Si j'exécute ces commandes à partir d'un script:

#my.sh
PWD=bla
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
xxx
bla

c'est bon.

Mais si je cours:

#my.sh
sed 's/xxx/'$PWD'/'
...
$ ./my.sh
$ sed: -e expression #1, char 8: Unknown option to `s' 

J'ai lu dans des tutoriels que pour substituer des variables d'environnement à partir de Shell, vous devez vous arrêter, et "citer" la partie $varname afin qu'elle ne soit pas substituée directement, ce que j'ai fait et qui ne fonctionne que si la variable est défini immédiatement avant.

Comment faire pour que sed puisse reconnaître un $var en tant que variable d'environnement tel qu'il est défini dans le shell?

160
Roman M

Vos deux exemples semblent identiques, ce qui rend les problèmes difficiles à diagnostiquer. Problèmes potentiels:

  1. Vous aurez peut-être besoin de guillemets doubles, comme dans sed 's/xxx/'"$PWD"'/'

  2. $PWD peut contenir une barre oblique. Dans ce cas, vous devez rechercher un caractère non contenu dans $PWD à utiliser comme délimiteur.

Pour résoudre les deux problèmes à la fois, peut-être

sed 's@xxx@'"$PWD"'@'
256
Norman Ramsey

En plus de la réponse de Norman Ramsey, j'aimerais ajouter que vous pouvez doubler la chaîne entière (ce qui rendrait la déclaration plus lisible et moins sujette aux erreurs).

Donc, si vous souhaitez rechercher 'foo' et le remplacer par le contenu de $ BAR, vous pouvez inclure la commande sed entre guillemets.

sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"

Dans la première, $ BAR ne se développera pas correctement tandis que dans la deuxième $ BAR se développera correctement.

91
Jeach

Vous pouvez utiliser d'autres caractères en plus de "/" en substitution:

sed "s#$1#$2#g" -i FILE
55
Paulo Fidalgo

Une autre alternative facile:

Puisque $PWD contient généralement une barre oblique /, utilisez | au lieu de / pour l'instruction sed:

sed -e "s|xxx|$PWD|"
43
Thales Ceolin

Avec votre question modifier, je vois votre problème. Supposons que le répertoire en cours est /home/yourname ... dans ce cas, votre commande ci-dessous:

sed 's/xxx/'$PWD'/'

sera étendu à

sed `s/xxx//home/yourname//

ce qui n'est pas valide. Vous devez mettre un caractère \ devant chaque / dans votre $ PWD si vous voulez le faire.

13
Eddie

mauvaise manière: changer le délimiteur

sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'

peut-être que ce n'est pas la réponse finale,

vous ne pouvez pas savoir quel caractère se produira dans $PWD, /: OR @.

le bon moyen est de remplacer le caractère spécial dans $PWD.

bonne voie: délimiteur d'échappement

par exemple:

utiliser / comme délimiteur

echo ${url//\//\\/}
x.com:80\/aa\/bb\/aa.js

echo ${url//\//\/}
x.com:80/aa/bb/aa.js

echo "${url//\//\/}"
x.com:80\/aa\/bb\/aa.js

echo $tmp | sed "s/URL/${url//\//\\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

echo $tmp | sed "s/URL/${url//\//\/}/"
<a href="x.com:80/aa/bb/aa.js">URL</a>

OR

utilisez : comme délimiteur (plus lisible que /)

echo ${url//:/\:}
x.com:80/aa/bb/aa.js

echo "${url//:/\:}"
x.com\:80/aa/bb/aa.js

echo $tmp | sed "s:URL:${url//:/\:}:g"
<a href="x.com:80/aa/bb/aa.js">x.com:80/aa/bb/aa.js</a>
4
yurenchen
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

où VAR contient ce que vous souhaitez remplacer par ce champ

3
PsychoData

En fait, la chose la plus simple (du moins en général) consiste à utiliser un séparateur différent pour la commande sed substitution (s). Donc, au lieu de s/pattern/'$ mypath'/en cours d’extension vers s/pattern // my/path/qui va bien sûr confondre la commande s, utilisez s! Pattern! '$ Mypath'! qui sera étendu à s! pattern!/my/path! J'ai utilisé le caractère bang (!) (Ou tout ce que vous voulez) qui évite la barre oblique habituelle, mais qui ne veut pas dire, c'est-à-dire votre choix uniquement comme séparateur.

3
adeger

J'ai eu un problème similaire, j'avais une liste et je dois construire un script SQL basé sur un modèle (qui contenait @INPUT@ comme élément à remplacer):

for i in LIST 
do
    awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
1
aniskop

Traitement des VARIABLES dans sed

[root@gislab00207 ldom]# echo domainname: None > /tmp/1.txt

[root@gislab00207 ldom]# cat /tmp/1.txt

domainname: None

[root@gislab00207 ldom]# echo ${DOMAIN_NAME}

dcsw-79-98vm.us.Oracle.com

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: ${DOMAIN_NAME}/g'

 --- Below is the result -- very funny.

domainname: ${DOMAIN_NAME}

 --- You need to single quote your variable like this ... 

[root@gislab00207 ldom]# cat /tmp/1.txt | sed -e 's/domainname: None/domainname: '${DOMAIN_NAME}'/g'


--- The right result is below 

domainname: dcsw-79-98vm.us.Oracle.com
1