$ bash -version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
次のシェルスクリプトを考えてみましょう。
#!/bin/bash
declare -A PROVS=( ["NL"]=10 ["PE"]=11 ["NS"]=12 ["NB"]=13 ["QC"]=24 ["ON"]=35 ["MB"]=46 ["SK"]=47 ["AB"]=48 ["BC"]=59 ["YK"]=60 ["NT"]=61 ["NU"]=62 )
for key in "${!PROVS[@]}" ; do \
touch "foo_${key}_${PROVS[${key}]}" ; \
done
Makefileで同等の操作を実行しようとしています。
SHELL := /bin/bash
.PHONY: foo
foo:
declare -A PROVS=( ["NL"]=10 ["PE"]=11 ["NS"]=12 ["NB"]=13 ["QC"]=24 ["ON"]=35 ["MB"]=46 ["SK"]=47 ["AB"]=48 ["BC"]=59 ["YK"]=60 ["NT"]=61 ["NU"]=62 )
for key in "$${!PROVS[@]}" ; do \
touch "foo_$${key}_$${PROVS[$${key}]}" ; \
done
私はいません。本物touch
ファイルが欲しいです。できないため、これを行っています@echo
。ループ内にあるため、@は行の先頭にあるとは見なされません。それともそういうことが起きているようです。
とにかくポイントは、ループがまったく実行されていないようで、touch
/echo
ビジネスが発生することです。上記のシェルスクリプトの内容はmake
端末に正確に反映されます。私はshebangを追加し、完全なチェックで実行しました。魅力のように働いた。
通常の配列を使用すると問題はありません。
for prov in NL PE NS NB QC ON MB SK AB BC YK NT NU ; do \
しかし、これらのコード(10、11など)も必要です。
誰もこれについての洞察力を持っていますか?
必要はありませんが、「declare -A」を使用しながら、ファイルの上部にPROVS変数を割り当てる方法(または可能かどうか)も知りたいです。
編集する: 私はMakefileの例をめちゃくちゃにして、インラインシェルコマンドに過ぎず、もはやレシピではありません。明確な説明のために、「foo:」ターゲットを再追加しました。
答え1
抜粋したコードが合理的に代表的な場合は、BashコマンドをMakefileに直接入力し、MakeがBashを使用してそのコマンドを実行することを期待しているようです。そのようなことは起こりませんでした。 Makefileの構文はまったく異なります。 以内にレシピの場合は、Bashコマンドを入力できます。レシピの各行は別々のサブシェルで実行されます。したがって、少なくとも2つの変更が必要です。
- シェルコマンドがターゲットに存在する必要があります。
declare
ループと同じシェルで実行する必要があります。それ以外の場合は、declare
Bashインスタンスに存在し、そのインスタンスを終了し、現在欠落している必要がない別のインスタンスでループを実行しますdeclare
。
これは、これらの変更を適用したMakefileの簡単なリファクタリングです。
SHELL=/bin/bash # This is the standard compliant method
.PHONY: all
all:
declare -A PROVS=( ["NL"]=10 ["PE"]=11 ["NS"]=12 ["NB"]=13 \
["QC"]=24 ["ON"]=35 ["MB"]=46 ["SK"]=47 ["AB"]=48 \
["BC"]=59 ["YK"]=60 ["NT"]=61 ["NU"]=62 )\
; for key in "$${!PROVS[@]}" ; do \
touch "foo_$${key}_$${PROVS[$${key}]}" ; \
done
@
コマンドを自動的に実行するルールは、コマンドライン全体に適用されます。したがって、上記の項目の前に配置することができます。declare
この場合、コマンドライン全体がBashに送信される前に削除されます。他の場所では削除または理解されず、呼び出しシェルでBash構文エラーが発生しているようです。
(ルールへのこだわりはとにかくまたは@
半パターンです。make -s
出力を見たくない場合は実行してください。終了すると、make
ルールのデバッグがより困難になるだけです。)