SED замена для переменной

У меня есть файл с именем check.txt, который имеет следующее содержимое:

$ cat check.txt
~/bin/tibemsadmin -server $URL-user $USER -password $PASWRD
$

У меня есть основной сценарий, где значения $URL, $USER, $PASWRD получены из основного сценария. Я хочу использовать утилиту SED для замены $URL, $USER, $PASWRD на фактические значения в файле check.txt.

Я пытаюсь так, но это не удается.

emsurl=tcp://myserver:3243
emsuser=test
emspasswd=new
sed s/$URL/${emsurl}/g check.txt >> check_new.txt
sed s/$USER/${emsuser}/g check.txt_new.txt >> check_new_1.txt
sed s/PASWRD/${emspasswd}/g check_new_1.txt >> final.txt

Мой вывод final.txt желателен, как показано ниже:

~/bin/tibemsadmin -server tcp://myserver:3243 -user test -password new

Не могли бы вы мне помочь?

4 ответа

Вы должны быть довольно осторожны с использованием цитат. Вам также необходимо научиться выполнять несколько операций за один проход и / или как использовать каналы.

emsurl=tcp://myserver:3243
emsuser=test
emspasswd=new
sed -e "s%\$URL%${emsurl}%g" \
    -e "s%\$USER%${emsuser}%g" \
    -e "s%\$PASWRD%${emspasswd}%g" check.txt >final.txt

Ваша проблема в том, что оболочка расширила '$URL' в вашей командной строке (вероятно, до нуля), что означает, что sed должен увидеть что-то другое, чем вы хотели. Избегая $ с \, sed получает возможность увидеть то, что вы намеревались.

Обратите внимание, что я изначально использовал / в качестве разделителя в замещающих операциях; однако, как справедливо отмечает DarkDust, это не сработает, поскольку в URL-адресах есть косые черты. Мой нормальный запасной персонаж % - как сейчас показано - но это может появляться в некоторых URL-адресах и может не подходить. Я бы, вероятно, использовал контрольный символ, такой как control-A, если бы мне пришлось беспокоиться об этом - или я использовал бы Perl, который мог бы играть без запутывания.

Вы также можете объединить три отдельных -e выражения в одно с заменой их точкой с запятой. Однако я предпочитаю четкость трех операций, четко разделенных.

Вы можете использовать немного другой подход, изменив свой основной скрипт следующим образом:

export URL="tcp://myserver:3243"
export USER=test
export PASWRD=new
. ./check.txt

Это устанавливает переменные и затем запускает check.txt в контексте вашего основного скрипта

Хотя вы не говорите, что не получается, я думаю, я вижу проблемы.

Я предлагаю вам сделать это:

sed "s|\$URL|${emsurl}|g"

То есть первый $ нужно избежать, потому что вы хотите буквально. Тогда вместо / Я предлагаю вам использовать | (труба) как разделитель, так как он не используется в ваших строках. Наконец, используйте " чтобы содержимое интерпретировалось оболочкой как строка.

Затем вы можете передать все вместе, чтобы не нуждаться во временных файлах:

sed "s|\$URL|${emsurl}|g" | sed "s|\$USER|${emsuser}|g" | sed "s|\$PASSWRD|${emspasswd}|g"

Подстановка переменной должна быть вне выражения sed, а '$' должно быть экранировано; в вашем случае что-то вроде этого:

sed -e 's/\$URL/'$emsurl'/g' -e 's/\$USER/'$emsuser'/g' -e 's/\$PASSWORD/'$emaspasswd'/g'

В любом случае, на вашем месте я бы не использовал $ для сопоставления заполнителей в файле шаблона, потому что это вызывает путаницу с переменными BASH, вместо этого используйте другой шаблон (например, @URL@).

Другие вопросы по тегам