Shell
shell變數測試擴展問題
我有這個程式碼:
sed \ $( (( $compress == 1 )) && echo -n '-e /^RMTHOST/ s/$/, compress/' ) \ -e "s|\*\*jobname\*\*|$jobname|g" \ -e "s|\*\*hostname\*\*|$hostname|g" \ -e "s|\*\*hostport\*\*|$hostport|g" \ -e "s|\*\*rmttrailname\*\*|$rmttrailname|g" < $GGPARAMSDIR/pump.template > $GGPARAMSDIR/$jobname.prm
這幾乎像我想要的那樣工作。如果
$compress == 1
,我希望sed
包含字元串-e /^RMTHOST/ s/$/, compress/'
。如果$compress != 1
,則不包括該部分。我收到以下錯誤時
$compress is 1
sed: -e expression #1, char 10: missing command
當我將 set -x 添加到腳本進行調試時,它會擴展為以下內容:
sed -e '/^RMTHOST/' 's/$/,' compress/ -e 's|\*\*jobname\*\*|pssic|g' -e 's|\*\*hostname\*\*|omsssi|g' -e 's|\*\*hostport\*\*|7809|g' -e 's|\*\*rmttrailname\*\*|./dirdat/dsn/rc|g'
請注意在 之後關閉第一個
-e
表達式的單個刻度/^RMTHOST/
,我確定這是我的問題的原因。但我無法弄清楚修復它的語法。僅供參考,變數的值為
jobname=pssic
、hostname=omsssi
和hostport=7809
任何人都可以幫忙嗎?
問題
問題是命令替換的結果會受到路徑名擴展和分詞的影響。
要查看命令替換的輸出會發生什麼,讓我們使用
printf
它來顯示它產生的單詞:$ printf ">%s<\n" $( (( compress == 1 )) && echo -n '-e /^RMTHOST/ s/$/, compress/' ) >-e< >/^RMTHOST/< >s/$/,< >compress/<
你確實需要
-e
一個單獨的詞。但是請注意,分詞也導致 sed 替換命令被分解為 sed無法理解的內容:$ sed -e '/^RMTHOST/' 's/$/,' 'compress/' sed: -e expression #1, char 10: missing command
解決方案
嘗試改用 bash 數組:
#!/bin/bash jobname=pssic hostname=omsssi hostport=7809 compress=1 rmttrailname=SomethingElse args=() (( compress == 1 )) && args+=('-e' '/^RMTHOST/ s/$/, compress/') args+=( -e "s|\*\*jobname\*\*|$jobname|g" -e "s|\*\*hostname\*\*|$hostname|g" -e "s|\*\*hostport\*\*|$hostport|g" -e "s|\*\*rmttrailname\*\*|$rmttrailname|g" ) declare -p args # Optional: Verify the args are what we want. sed "${args[@]}" <"$GGPARAMSDIR/pump.template" >"$GGPARAMSDIR/$jobname.prm"
好讀
關於從 shell 變數創建命令的問題的一個有趣且更普遍的討論是:“我試圖將命令放入變數中,但複雜的情況總是失敗!”