Подстановка переменных окружения в sed



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



#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'


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



как я могу заставить sed распознать $var как переменная окружения, как она есть определяется в оболочке?

794   10  

10 ответов:

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

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

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

прибить оба вопроса сразу, возможно

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

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

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

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

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

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

sed "s###g" -i FILE

еще один простой вариант:

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

sed -e "s|xxx|$PWD|"

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

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

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

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

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

VAR=8675309
echo "abcde:jhdfj$jhbsfiy/.hghi$jh:12345:dgve::" |\
sed 's/:[0-9]*:/:'$VAR':/1' 

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

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

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

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>

или

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

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>

работа с переменными в 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

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

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

Comments

    Ничего не найдено.