Makefileでbash連想配列を繰り返す

Makefileでbash連想配列を繰り返す
$ 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ループと同じシェルで実行する必要があります。それ以外の場合は、declareBashインスタンスに存在し、そのインスタンスを終了し、現在欠落している必要がない別のインスタンスでループを実行します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

デモ:http://ideone.com/t94AOB

@コマンドを自動的に実行するルールは、コマンドライン全体に適用されます。したがって、上記の項目の前に配置することができます。declareこの場合、コマンドライン全体がBashに送信される前に削除されます。他の場所では削除または理解されず、呼び出しシェルでBash構文エラーが発生しているようです。

(ルールへのこだわりはとにかくまたは@半パターンです。make -s出力を見たくない場合は実行してください。終了すると、makeルールのデバッグがより困難になるだけです。)

おすすめ記事