Bash 文字列の評価が不明瞭

Bash 文字列の評価が不明瞭

bash スクリプトで次のことを考慮してください。

STOP_SEARCH_STR="'""for $TASKNAME""'"
echo $STOP_SEARCH_STR               # prints 'for Our Special Task_4'
echo "$STOP_SEARCH_STR"             # prints 'for Our Special Task_4'
echo "grep -F "$STOP_SEARCH_STR" "$TEMP"/draft" # prints grep -F 'for Our Special Task_4' /tmp/draft
echo "$(grep -F "$STOP_SEARCH_STR" "$TEMP"/draft)"  # prints nothing!
echo $("grep -F "$STOP_SEARCH_STR" "$TEMP"/draft")  # prints nothing!

$TEMP/draft テキスト ファイルの内容は次のとおりです。

2019-11-21 08:13:58,825 Task started: 'Our Special Task_4' of type 'Our - Special Task' 
2019-11-21 08:14:10,509 Task ended: 'Success' for Our Special Task_4 -- Elapsed time: 11.0 seconds

もし私が手動でコマンドを入力するとgrep -F 'for Our Special Task_4' /tmp/draft、ドラフトテキストファイルの 2 行目が表示されます。

2019-11-21 08:14:10,509 Task ended: 'Success' for Our Special Task_4 -- Elapsed time: 11.0 seconds

しかし、上記の最後の 2 つのコマンド (bash スクリプト内) は何も出力しません。

理由が分かりますか?

答え1

変数が展開された後は引用符は特別な意味を持ちません。

TASKNAMEが含まれていると仮定するOur Special Task_4と、引用符を含めて はSTOP_SEARCH_STRに設定されます。これが に表示される内容です。'for Our Special Task_4'echo

を実行すると、検索する文字列grep -F "$STOP_SEARCH_STR" "$TEMP"/draftが指定されます。その文字列はファイル内に存在しないため、一致する行はなく、何も出力されません。grep'for Our Special Task_4'grep

引用符を削除してください。探しているものではありません。

task="Our Special Task_4"
str="for $task"
grep -F "$str" "$TEMP/draft"

注: あなたする変数展開を二重引用符で囲む必要がある"$str"場合や"$STOP_SEARCH_STR"単語の分割を防ぐ場合は、シェル スクリプトが空白文字やその他の特殊文字で動作しなくなるのはなぜですか?

あなたが手動でコマンドを入力するとgrep -F 'for Our Special Task_4' /tmp/draft、引用符はシェル構文の一部となり、引用符内のスペースの特別な意味が実質的に削除されます。これは、通常の文字のように動作する変数内の引用符とは異なります。


余談ですが、1) はecho "$(somecmd)"通常は冗長なので、そのまま実行できますsomecmd。2) ここではecho $("grep -F "$STOP_SEARCH_STR" "$TEMP"/draft")、引用符が空白を囲んでいるため、 というコマンドを実行しようとしていますgrep -F 'for。おそらく、その場合はエラーが発生するはずです。

$ echo $("grep -F "$STOP_SEARCH_STR" "$TEMP"/draft")
bash: grep -F 'for: command not found

答え2

次の行を変更する必要があります:

STOP_SEARCH_STR="'""for $TASKNAME""'"

この行に追加します (はい、一重引用符は必要ありません。役に立ちません):

STOP_SEARCH_STR="for $TASKNAME"

そして、スクリプト内で次の行を使用します (はい、示されているように引用されています)。

grep -F "$STOP_SEARCH_STR" "$TEMP"/draft

echo を追加したい/追加する必要がある場合 (これは不要であり、問​​題を引き起こす可能性もあります)、次の行を使用します (はい、すべての展開 (変数とサブシェル) を引用符で囲みます)。

echo "$(grep -F "$STOP_SEARCH_STR" "$TEMP"/draft")"

関連情報