Подтвердить что ты не робот

Как заменить переменную в оболочке script string

У меня проблемы с работой...

У меня есть переменная, содержащая SQL с заполнителем:

echo $SQL
SELECT PX_PROMOTION_ID, PRIORITY, STATUS, EXCLSVE, TYPE, PERORDLMT, PERSHOPPERLMT, TOTALLMT, RSV_INT, PX_GROUP_ID, CAMPAIGN_ID, STOREENT_ID, VERSION, REVISION, EFFECTIVE, TRANSFER, CDREQUIRED, EXPIRE, LASTUPDATEBY, TO_CHAR(LASTUPDATE, 'YYYYMMDD HH24MMSS') AS LASTUPDATE, TO_CHAR(STARTDATE, 'YYYYMMDD HH24MMSS') AS STARTDATE, TO_CHAR(ENDDATE, 'YYYYMMDD HH24MMSS') AS ENDDATE, TO_CHAR(RSV_TIME, 'YYYYMMDD HH24MMSS') AS RSV_TIME, RSV_REAL, TGTSALES, NAME, CODE, RSV_VCH, OPTCOUNTER FROM PX_PROMOTION WHERE LASTUPDATE BETWEEN (SELECT MAX(BATCHSTART) FROM XRPTEBATCHCONTROL) AND TIMESTAMP('$BATCH_END')

У меня есть другая переменная, которая содержит значение:

echo $BATCH_END
2012-11-14 17:06:13

Я хочу заменить заполнитель значением. Я не особенно хорошо разбираюсь в сценариях Unix, но я пробовал это:

echo $SQL | sed -e "s/'$BATCH_END/$BATCH_END/g"

но он все равно не заменяется...

Может ли кто-нибудь помочь? Я хочу заменить местозаполнитель и сохранить окончательную строку, назначенную для $SQL

Мне также нужно знать, как вернуть значение возвращаемого значения в переменную, например, я попытался:

 SQL=`echo "$SQL" | echo "${SQL//\$BATCH_END/$BATCH_END}"`
4b9b3361

Ответ 1

Вам не хватает конца этой пары с одной кавычкой в ​​ script.

Изменить:

echo $SQL | sed -e "s/'$BATCH_END/$BATCH_END/g"

To:

echo $SQL | sed -e "s/\$BATCH_END/$BATCH_END/g"

Обновлено - в соответствии с комментарием:

Чтобы сохранить результат вышеуказанной замены в $SQL, выполните одно из следующих действий:

# Preferred way
SQL=$(echo $SQL | sed -e "s/\$BATCH_END/$BATCH_END/g")

# Old way
SQL=`echo $SQL | sed -e "s/\$BATCH_END/$BATCH_END/g"`

Это называется подстановка команды. Любой синтаксис ($(...) по сравнению с оболочкой по обратным каналам) работает, но предпочтительный позволяет вам вложенности.

Предпочтительный предпочтительный способ: Herestring

Это, вероятно, немного более продвинутое, чем то, о чем вы заботитесь, но его выполнение следующим образом избавит вас от подпроцесса от необходимости использовать echo без необходимости:

SQL=$(sed -e "s/\$BATCH_END/$BATCH_END/g" <<< $SQL)

Ответ 2

В моем терминале:

$ SQL="SELECT PX_PROMOTION_ID, PRIORITY, STATUS, EXCLSVE, TYPE, PERORDLMT, PERSHOPPERLMT, TOTALLMT, RSV_INT, PX_GROUP_ID, CAMPAIGN_ID, STOREENT_ID, VERSION, REVISION, EFFECTIVE, TRANSFER, CDREQUIRED, EXPIRE, LASTUPDATEBY, TO_CHAR(LASTUPDATE, 'YYYYMMDD HH24MMSS') AS LASTUPDATE, TO_CHAR(STARTDATE, 'YYYYMMDD HH24MMSS') AS STARTDATE, TO_CHAR(ENDDATE, 'YYYYMMDD HH24MMSS') AS ENDDATE, TO_CHAR(RSV_TIME, 'YYYYMMDD HH24MMSS') AS RSV_TIME, RSV_REAL, TGTSALES, NAME, CODE, RSV_VCH, OPTCOUNTER FROM PX_PROMOTION WHERE LASTUPDATE BETWEEN (SELECT MAX(BATCHSTART) FROM XRPTEBATCHCONTROL) AND TIMESTAMP('\$BATCH_END')"
$ # (observe: I escaped the $ sign to have the same variable as you)
$ echo "$SQL"
SELECT PX_PROMOTION_ID, PRIORITY, STATUS, EXCLSVE, TYPE, PERORDLMT, PERSHOPPERLMT, TOTALLMT, RSV_INT, PX_GROUP_ID, CAMPAIGN_ID, STOREENT_ID, VERSION, REVISION, EFFECTIVE, TRANSFER, CDREQUIRED, EXPIRE, LASTUPDATEBY, TO_CHAR(LASTUPDATE, 'YYYYMMDD HH24MMSS') AS LASTUPDATE, TO_CHAR(STARTDATE, 'YYYYMMDD HH24MMSS') AS STARTDATE, TO_CHAR(ENDDATE, 'YYYYMMDD HH24MMSS') AS ENDDATE, TO_CHAR(RSV_TIME, 'YYYYMMDD HH24MMSS') AS RSV_TIME, RSV_REAL, TGTSALES, NAME, CODE, RSV_VCH, OPTCOUNTER FROM PX_PROMOTION WHERE LASTUPDATE BETWEEN (SELECT MAX(BATCHSTART) FROM XRPTEBATCHCONTROL) AND TIMESTAMP('$BATCH_END')
$ BATCH_END="2012-11-14 17:06:13"
$ echo "$BATCH_END"
2012-11-14 17:06:13
$ # Now the replacement:
$ echo "${SQL//\$BATCH_END/$BATCH_END}"
SELECT PX_PROMOTION_ID, PRIORITY, STATUS, EXCLSVE, TYPE, PERORDLMT, PERSHOPPERLMT, TOTALLMT, RSV_INT, PX_GROUP_ID, CAMPAIGN_ID, STOREENT_ID, VERSION, REVISION, EFFECTIVE, TRANSFER, CDREQUIRED, EXPIRE, LASTUPDATEBY, TO_CHAR(LASTUPDATE, 'YYYYMMDD HH24MMSS') AS LASTUPDATE, TO_CHAR(STARTDATE, 'YYYYMMDD HH24MMSS') AS STARTDATE, TO_CHAR(ENDDATE, 'YYYYMMDD HH24MMSS') AS ENDDATE, TO_CHAR(RSV_TIME, 'YYYYMMDD HH24MMSS') AS RSV_TIME, RSV_REAL, TGTSALES, NAME, CODE, RSV_VCH, OPTCOUNTER FROM PX_PROMOTION WHERE LASTUPDATE BETWEEN (SELECT MAX(BATCHSTART) FROM XRPTEBATCHCONTROL) AND TIMESTAMP('2012-11-14 17:06:13')

Готово!

Ответ 3

Вам нужно процитировать первый $, чтобы он не расширялся как переменная оболочки.

echo "$SQL" | sed -e "s/'\$BATCH_END'/'$BATCH_END'/g"

... Или выберите более простой заполнитель, например, @[email protected].

Чтобы вернуть результат в $SQL, вам понадобится еще несколько экранов оболочки:

SQL=`echo "$SQL" | sed -e "s/'\\\$BATCH_END'/'$BATCH_END'/g"`

Ответ 4

Один из способов сделать это - "дифференциальное цитирование" в одном аргументе:

echo "$SQL" | sed -e 's/$BATCH_END/'"$BATCH_END/g"

Первая часть опции -e находится в одинарных кавычках, поэтому оболочка не расширяет первый $BATCH_END и может соответствовать слову в инструкции SQL. Вторая часть находится в двойных кавычках, поэтому оболочка расширяет вторую $BATCH_END и помещает ее текст в SQL.

Если вам нужно беспокоиться о одиночных кавычках вокруг $BATCH_END, вам придется играть в другие трюки; вероятно, обратная косая черта была бы простейшей (и в любом случае это жизнеспособный вариант):

echo "$SQL" | sed -e "s/'\$BATCH_END'/'$BATCH_END'/g"

Обратная косая черта останавливает оболочку, расширяющую первый $BATCH_END, но отсутствие обратного слэша означает, что вторая расширяется. Внутри двойных кавычек одиночные кавычки теряют свойство "без расширения".

Ответ 5

Проблема заключается в том, что вы используете строку с двойными кавычками в оболочке. В строке с двойными кавычками переменные типа $BATCH_END интерпретируются как переменные оболочки и интерполируются. Символ ' не имеет особого значения в строке с двойными кавычками; это не предотвращает интерполирование переменных. Таким образом, ваша строка $BATCH_END заменяется в обоих местах; ваш вызов sed эквивалентен:

sed -e "s/'2012-11-14 17:06:13/2012-11-14 17:06:13/"

Как вы можете видеть, это не очень полезно (у вас также есть паразитный '). Вам нужно избежать знака $, чтобы он не интерпретировался как переменная оболочки:

sed -e "s/\$BATCH_END/$BATCH_END/"