Если я запустил эти команды из script:
#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
как переменную среды, как она определена в оболочке?
Два примера выглядят одинаково, что затрудняет диагностику проблем. Возможные проблемы:
Вам могут потребоваться двойные кавычки, как в sed 's/xxx/'"$PWD"'/'
$PWD
может содержать косую черту, в этом случае вам нужно найти символ, не содержащийся в $PWD
, для использования в качестве разделителя.
Чтобы одновременно прикрыть оба вопроса, возможно,
sed 's@xxx@'"$PWD"'@'
В дополнение к ответу Нормана Рэмси, я бы хотел добавить, что вы можете сдвоить две строки всей строки (что может сделать утверждение более понятным и менее подверженным ошибкам).
Итак, если вы хотите найти "foo" и заменить его содержимым в $BAR, вы можете заключить команду sed в двойные кавычки.
sed 's/foo/$BAR/g'
sed "s/foo/$BAR/g"
В первом случае $BAR не будет правильно расширяться, а во втором $BAR будет правильно расширяться.
Вы можете использовать другие символы, кроме "/", в подстановке:
sed "s#$1#$2#g" -i FILE
sed
преувеличивал из-за интерпретации /
в содержимом $ 2. Это было именно то, что мне нужно, чтобы пройти через это. Спасибо за отличный совет!
Другая простая альтернатива:
Так как $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 содержит то, что вы хотите заменить поле
sed 's/xxx/'"$PWD"'/'
sed 's:xxx:'"$PWD"':'
sed 's@xxx@'"$PWD"'@'
может быть, это не окончательный ответ,
вы не можете знать, какой будет символ в $PWD
, /
:
OR @
.
хороший способ - заменить специальный символ в $PWD
.
например:
использовать /
как разделитель
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>
На самом деле, самая простая вещь (по крайней мере, в gnu sed) заключается в использовании другого разделителя для команды подстановки sed. Таким образом, вместо s/pattern/'$ mypath//расширяется до s/pattern//my/path/, который, конечно же, путает команду s, используйте s! Pattern!' $Mypath '! который будет расширен до s! pattern!/my/path! Я использовал символ Bang (!) (Или использую все, что вам нравится), что позволяет избежать обычного, но не по-вашему-единственного выбора, косой чертой в качестве разделителя.
Работа с VARIABLES внутри 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 script на основе шаблона (содержащего @INPUT@
как заменяемый элемент):
for i in LIST
do
awk "sub(/\@INPUT\@/,\"${i}\");" template.sql >> output
done