回答:
以下は、私がを使用していることから推測できるように./a.out
、UNIXタイプのプラットフォームを使用している場合に実行されます。
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
次のようにテストします。
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
生成する:
1
2
3
4
範囲が広い場合は、次を使用します。
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
これにより、1から10までが出力さwhile
れます。コメントに示されているように、はるかに広い範囲で終了条件を10から1000に変更するだけです。
ネストされたループはこうして行うことができます:
target:
num1=1 ; while [[ $$num1 -le 4 ]] ; do \
num2=1 ; while [[ $$num2 -le 3 ]] ; do \
echo $$num1 $$num2 ; \
((num2 = num2 + 1)) ; \
done ; \
((num1 = num1 + 1)) ; \
done
生産:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
4 1
4 2
4 3
seq
番号のシーケンスを生成するコマンドは、ほとんど(すべて?)のUNIXシステム上に存在する、あなたが書くことができるようにfor number in ``seq 1 1000``; do echo $$number; done
ない2、(配列コマンドの両側に単一バッククォートを入れて、私はこれを正しくフォーマットする方法がわかりませんstackoverflowの構文を使用)
make
正常に実行するためのものとして、各ラインを扱う別のサブシェル。継続しfor number in 1 2 3 4 ; do
ないと、ループの残りを使わずに、(たとえば)だけでサブシェルを実行しようとします。これにより、実質的にの形式の1行になりwhile something ; do something ; done
、完全なステートメントになります。$$
質問はここで回答されていますstackoverflow.com/questions/26564825/...を、一見この非常に答えから抽出されたコード:-)で
GNU makeを使用している場合は、
数= 1 2 3 4 やれ: $(foreach var、$(NUMBERS)、。/ a.out $(var);)
生成して実行します
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
./a.out 1
。./a.out 2
関係なく実行されます。
メイク私見を使用する主な理由はある-j
フラグ。make -j5
一度に5つのシェルコマンドを実行します。これは、CPUが4つある場合に適しています。また、メイクファイルのテストも適切です。
基本的には、次のようなものを表示したいとします。
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
これは-j
友好的です(良い兆候)。ボイラープレートを見つけられますか?次のように書くことができます:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
同じ効果のため(はい、これはmakeに関する限り、以前の定式化と同じですが、少しコンパクトです)。
コマンドラインで制限を指定できるようにするためのパラメーター化のさらなるビット(make
適切な算術マクロがないので面倒なので、ここでカンニングして使用します$(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
これをmake -j5 LAST=550
で実行しLAST
ます。デフォルトは1000です。
.PHONY: all
、makeはというファイルを探しますall
。そのようなファイルが存在する場合、makeは次にそのファイルの最終変更時刻をチェックします。メイクファイルはほぼ確実に意図したとおりに動作しません。.PHONY
宣言は、make告げるall
象徴的なターゲットですが。したがって、Makeはall
ターゲットが常に古くなっていると見なします。完璧です。マニュアルを参照してください。
%
は、ルールと一致するものはすべて$*
レシピのように使用できるという便宜のために使用します。
私は質問が数年前のものであることを理解していますが、この投稿は上記とは異なるアプローチを示し、シェル操作にも依存せず、開発者がハードコードされたコードを削除する必要もないので、誰かに役立つかもしれません数値の文字列。
$(eval ....)組み込みマクロはあなたの友達です。または少なくともすることができます。
define ITERATE
$(eval ITERATE_COUNT :=)\
$(if $(filter ${1},0),,\
$(call ITERATE_DO,${1},${2})\
)
endef
define ITERATE_DO
$(if $(word ${1}, ${ITERATE_COUNT}),,\
$(eval ITERATE_COUNT+=.)\
$(info ${2} $(words ${ITERATE_COUNT}))\
$(call ITERATE_DO,${1},${2})\
)
endef
default:
$(call ITERATE,5,somecmd)
$(call ITERATE,0,nocmd)
$(info $(call ITERATE,8,someothercmd)
これは単純な例です。大きな値の場合は適切にスケーリングされません-機能しますが、ITERATE_COUNT文字列は反復ごとに2文字(スペースとドット)ずつ増加するため、数千に達すると、単語を数えるのに徐々に時間がかかります。書かれているように、それはネストされた反復を処理しません(そうするには、別個の反復関数とカウンターが必要になります)。これは純粋にgnu makeであり、シェル要件はありません(もちろん、OPは毎回プログラムを実行しようとしていましたが、ここでは単にメッセージを表示しています)。$(word ...)はエラーになるため、ITERATE内のifは値0をキャッチすることを目的としています。
$(words ...)ビルトインはアラビア語のカウントを提供できるため、カウンターとして機能する成長する文字列が使用されますが、makeはそれ以外の場合は数学演算をサポートしません(1 + 1を何かに割り当てて2を取得することはできません)シェルから何かを呼び出してそれを実行する場合、または同等に複雑なマクロ操作を使用する場合を除きます)。これはINCREMENTALカウンターではうまく機能しますが、DECREMENTカウンターではうまく機能しません。
私自身はこれを使用していませんが、最近、再帰関数を作成して、マルチバイナリ、マルチライブラリのビルド環境全体でライブラリの依存関係を評価する必要がありました。それ自体には他の依存関係(一部はビルドパラメーターによって異なる)があり、上記と同様に$(eval)とカウンターメソッドを使用します(私の場合、カウンターは、どういうわけか無限に進まないようにするために使用されますループ、およびどれだけの反復が必要であったかを報告する診断としても)。
OPのQにとって重要ではないが、他に価値のある何か:$(eval ...)は、循環参照に対するmakeの内部の嫌悪を回避するメソッドを提供します。これは、変数がマクロタイプ( =)、対即時割り当て(:=で初期化)。独自の割り当て内で変数を使用できるようにしたい場合があります。$(eval ...)を使用すると、それを実行できます。ここで考慮すべき重要なことは、evalを実行すると、変数が解決され、解決された部分はマクロとして扱われなくなることです。あなたが何をしているのかを知っていて、自分自身への割り当てのRHSで変数を使用しようとしている場合、これは通常、とにかく実行したいことです。
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
ハッピーメイク。
クロスプラットフォームサポートの場合、コマンドセパレーター(同じ行で複数のコマンドを実行するため)を構成可能にします。
たとえば、WindowsプラットフォームでMinGWを使用している場合、コマンドセパレータは&
次のようになります。
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
これにより、連結されたコマンドが1行で実行されます。
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
他で言及されているように、* nixプラットフォームではを使用しますCMDSEP = ;
。
これは質問に対する純粋な答えではありませんが、そのような問題を回避するインテリジェントな方法です。
複雑なファイルを作成する代わりに、たとえばmakefileのようなbashスクリプトに制御を委任するだけです。
foo : bar.cpp baz.h
bash script.sh
そしてscript.shは次のようになります:
for number in 1 2 3 4
do
./a.out $number
done
eval echo \$${$(var)}
; \ echo $$ var1; \((NUM = NUM + 1)); \ done all:set_var here SSA_CORE0_MAINEXECはすでに設定されている環境変数です。そのため、変数var1を使用してその値を評価または出力してもらいたいです。上記のように試してみましたが、うまくいきませんでした。助けてください。
bash
その機能を使用できます。ループは、これを実証できる機能の1つです。
set -e
forループのプレフィックスとして使用できます。例:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
終了コードですぐに終了します<> 0
。
がGNUmakeテーブルツールキットは、真の持っているwhile
ループを必要とされるものは、反復リストがある場合(実行のその二、三相を有するGNUmakeプログラミングの手段は何でも)、と簡単な解決策がありますinterval
。それを楽しむために、数値を16進数に変換します。
include gmtt/gmtt.mk
# generate a list of 20 numbers, starting at 3 with an increment of 5
NUMBER_LIST := $(call interval,3,20,5)
# convert the numbers in hexadecimal (0x0 as first operand forces arithmetic result to hex) and strip '0x'
NUMBER_LIST_IN_HEX := $(foreach n,$(NUMBER_LIST),$(call lstrip,$(call add,0x0,$(n)),0x))
# finally create the filenames with a simple patsubst
FILE_LIST := $(patsubst %,./a%.out,$(NUMBER_LIST_IN_HEX))
$(info $(FILE_LIST))
出力:
./a3.out ./a8.out ./ad.out ./a12.out ./a17.out ./a1c.out ./a21.out ./a26.out ./a2b.out ./a30.out ./a35.out ./a3a.out ./a3f.out ./a44.out ./a49.out ./a4e.out ./a53.out ./a58.out ./a5d.out ./a62.out
#I have a bunch of files that follow the naming convention
#soxfile1 soxfile1.o soxfile1.sh soxfile1.ini soxfile1.txt soxfile1.err
#soxfile2 soxfile2.o soxfile2.sh soxfile2.ini soxfile2.txt soxfile2.err
#sox... .... ..... .... .... ....
#in the makefile, only select the soxfile1.. soxfile2... to install dir
#My GNU makefile solution follows:
tgt=/usr/local/bin/ #need to use sudo
tgt2=/backup/myapplication/ #regular backup
install:
for var in $$(ls -f sox* | grep -v '\.' ) ; \
do \
sudo cp -f $$var ${TGT} ; \
cp -f $$var ${TGT2} ; \
done
#The ls command selects all the soxfile* including the *.something
#The grep command rejects names with a dot in it, leaving
#My desired executable files in a list.