Как заменить переменную в оболочке 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}"`
Ответы
Ответ 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/"