25

これを機能させるのに問題があります...

プレースホルダーを使用して 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}"`
4

7 に答える 7

48

スクリプトにその一重引用符のペアの終わりがありません。

から変更する:

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

に:

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)
于 2012-11-14T06:25:09.500 に答える
3

私の端末で:

$ 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')

終わり!

于 2012-11-14T06:32:00.710 に答える
1

$シェル変数として展開されないように、最初のものを引用する必要があります。

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

… または、たとえば、より簡単なプレースホルダーを選択@BATCH_END@します。

結果を割り当てるには、$SQLさらにシェルエスケープが必要になります。

SQL=`echo "$SQL" | sed -e "s/'\\\$BATCH_END'/'$BATCH_END'/g"`
于 2012-11-14T06:32:01.127 に答える
0

それを行う1つの方法は、単一の引数で「差分引用符」を使用することです:

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

オプションの最初の部分は-e一重引用符で囲まれているため、シェルは最初の部分を展開せず$BATCH_END、SQL ステートメント内の単語と一致させることができます。2 番目の部分は二重引用符で囲まれているため、シェルは 2 番目の部分を展開し、$BATCH_ENDそのテキストを SQL に配置します。

を一重引用符で囲む必要がある場合は$BATCH_END、別のトリックを実行する必要があります。おそらく、バックスラッシュが最も簡単です (とにかく実行可能なオプションです):

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

バックスラッシュは、最初のシェルの展開を停止しますが、$BATCH_ENDバックスラッシュがないということは、2 番目のシェルが展開されることを意味します。二重引用符内では、単一引用符は「展開なし」のプロパティを失います。

于 2012-11-14T06:32:07.180 に答える
0

問題は、シェルで二重引用符で囲まれた文字列を使用していることです。二重引用符で囲まれた文字列では、次のような変数$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/"
于 2012-11-14T06:32:36.430 に答える