Подстановка переменной среды в sed - PullRequest
155 голосов
/ 25 февраля 2009

Если я запускаю эти команды из скрипта:

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

хорошо.

Но, если я бегу:

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

Я читал в уроках, что для замены переменных окружения из оболочки вам нужно остановиться и «заключить в кавычки» часть $varname, чтобы она не заменялась напрямую, что я и сделал, и которая работает только в том случае, если переменная определяется непосредственно перед.

Как мне заставить sed распознать $var в качестве переменной среды, как она определена в оболочке?

Ответы [ 10 ]

247 голосов
/ 25 февраля 2009

Ваши два примера выглядят одинаково, что затрудняет диагностику проблем. Потенциальные проблемы:

  1. Возможно, вам понадобятся двойные кавычки, как в sed 's/xxx/'"$PWD"'/'

  2. $PWD может содержать косую черту, в этом случае вам необходимо найти символ , а не , содержащийся в $PWD, чтобы использовать его в качестве разделителя.

Чтобы решить обе проблемы одновременно, возможно

sed 's@xxx@'"$PWD"'@'
88 голосов
/ 14 апреля 2009

В дополнение к ответу Нормана Рэмси я хотел бы добавить, что вы можете заключить в кавычки всю строку (что может сделать оператор более читабельным и менее подверженным ошибкам).

Так что если вы хотите найти 'foo' и заменить его содержимым $ BAR, вы можете заключить команду sed в двойные кавычки.

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

В первом случае $ BAR не будет правильно расширяться, а во втором $ BAR будет расширяться правильно.

54 голосов
/ 08 марта 2012

Вы можете использовать другие символы, кроме "/", вместо:

sed "s#$1#$2#g" -i FILE
40 голосов
/ 17 апреля 2014

Еще одна простая альтернатива:

Поскольку $PWD обычно будет содержать косую черту /, используйте | вместо / для оператора sed:

sed -e "s|xxx|$PWD|"
13 голосов
/ 25 февраля 2009

С вашим вопросом редактирования я вижу вашу проблему. Допустим, текущим каталогом является /home/yourname ... в этом случае ваша команда ниже:

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

будет расширен до

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

, что недействительно. Вам нужно поставить символ \ перед каждым / в вашем $ PWD, если вы хотите сделать это.

3 голосов
/ 24 августа 2017

плохой способ: изменить разделитель

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

возможно, это не окончательный ответ,

Вы не можете знать, какой персонаж появится в $PWD, / : ИЛИ @.

хороший способ - заменить специальный символ в $PWD.

хороший способ: escape-разделитель

например:

используйте / в качестве разделителя

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

используйте : в качестве разделителя (более читабельно, чем /)

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>
3 голосов
/ 10 апреля 2013
VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

где VAR содержит то, что вы хотите заменить в поле

2 голосов
/ 27 января 2012

На самом деле, самая простая вещь (по крайней мере в gnu sed) - это использовать другой разделитель для команды sed substitution (s). Поэтому вместо того, чтобы s / pattern / '$ mypath' / была расширена до s / pattern // my / path /, что, конечно, запутает команду s, используйте s! Pattern! '$ Mypath'! который будет расширен до s! pattern! / my / path! В качестве разделителя я использовал символ взрыва (!) (Или что угодно), что позволяет избежать обычной косой черты «но не значит, что вы единственный выбор».

1 голос
/ 27 августа 2013

Работа с переменными внутри 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 голос
/ 25 марта 2013

У меня была похожая проблема, у меня был список, и мне нужно создать сценарий SQL на основе шаблона (который содержал @INPUT@ в качестве элемента для замены):

for i in LIST 
do
    awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...