DRY(反復しないでください)原則に従うためには、次のことを行う必要があります。ファイルの生成。したがって、そのファイルのどこかに次のレシピがあります。
shell=/bin/bash
# …
.ONESHELL:
run:
# Create bash sub-shell «cmd» var, holding a built-in test as a string
@cmd='[ $$(grep -iE _dev </etc/hosts | wc -l) -eq 0 ]'
# "$$" tells make to escape the dollar sign. So echoing …
@echo "$$cmd"
# gives «[ $(grep -iE _dev </etc/hosts | wc -l) -eq 0 ]» as I expected
# I need this variable to be expanded and interpreted as a real
# built-in square bracket test, so I wrote
@$$cmd && echo "Pass ! do more magical things …" || true
私は期待作るエスケープ$
記号$$cmd
⇒$cmd
が再び表示されます。強く打つ引用符で囲まれていない文字列をテストするには、コンテキストを括弧内に入れます。そうなんですか?
しかし、エラーが発生しました。/bin/bash: line 2: [: too many arguments
このエラーが発生する理由を知っている人はいますか?
Bashが私が期待するブラケットテストを提供しないのはなぜですか?
[ $(grep -iE _dev </etc/hosts | wc -l) -eq 0 ] && echo "Pass!"
ありがとうございます。
答え1
シェルの変数とコマンドの置換は、コマンド境界が決定され、リダイレクト(および割り当て)が解析された後に発生します。プログラム名および/またはパラメータを変数に入れて置き換えることはできますが、パイプ、リダイレクト、割り当て、またはシェル$( command )
キーワード(およびif
)などの他の代替エントリは使用できませんfor
。
この場合、コマンドを変更してテストを反転して交換して、パイプとトイレを取り外すことができます。
cmd='grep -qi _dev /etc/hosts' # note file as argument not redirection
$$cmd || do_blah
置換されたgrepコマンドは、ファイル内の一致するものが見つからないと自動的に失敗し、失敗するとdo_blahを実行します。
通常、値(プログラムパラメータだけでなく)を置き換えるときにシェル構文を使用するには、それを使用して値(または値)置換を実行するか(必要に応じて環境および/またはコマンド置換に応じて)eval
サブシェルを実行する必要があります。sh -c "$$cmd"
他のシェル))。
答え2
AはMakefile
シェルスクリプトではありません。すべての内容を次のように、よりシンプルできれいに作成できます。
#!/bin/sh
set -e
grep -q -iE _dev /etc/hosts
echo pass
...