Yanıtlar:
Bunu kullandığınızı varsaydığım gibi ./a.out
, UNIX tipi bir platformdaysanız aşağıdakiler yapılacaktır.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Aşağıdaki gibi test edin:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
üretir:
1
2
3
4
Daha büyük aralıklar için şunları kullanın:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Bu, 1'den 10'a kadar çıkışlar içerir while
, yorumunuzda belirtildiği gibi çok daha geniş bir aralık için sonlandırma koşulunu 10'dan 1000'e değiştirin .
İç içe döngüler şu şekilde yapılabilir:
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
üreten:
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
yazabilir bu yüzden bir sayı dizisidir çoğu (hepsi?) Unix sistemleri üzerinde var üretir komut for number in ``seq 1 1000``; do echo $$number; done
(seq komutu, iki değil her iki tarafında tek backtick koyun, bu doğru biçimlendirmek için nasıl bilmiyorum stackoverflow'un sözdizimini kullanıyor)
make
normalde her satıra ayrı bir alt kabukta çalışacak bir şey olarak davranmasıdır . Devam for number in 1 2 3 4 ; do
etmeden, döngünün geri kalanı olmadan sadece (örneğin) bir alt kabuk çalıştırmaya çalışırdı . Bununla birlikte, formun tek bir satırı haline gelir while something ; do something ; done
, bu tam bir ifadedir. $$
Sorumun yanıtı burada edilir: stackoverflow.com/questions/26564825/... , görünüşte :-) bu çok cevap çıkarılan kodla
GNU marka kullanıyorsanız, deneyebilirsiniz
SAYILAR = 1 2 3 4 yap: $ (foreach var, $ (NUMBERS),. / a.out $ (var);)
üretecek ve çalıştıracak
./a. çıkış 1; ./a. çıkış 2; ./a. çıkış 3; ./a. çıkış 4;
./a.out 1
. ./a.out 2
ne olursa olsun idam edilecek.
Kullanım yapmak IMHO başlıca nedenidir -j
bayrağı. make -j5
aynı anda 5 kabuk komutu çalıştırır. Bu, 4 CPU'nuz varsa ve herhangi bir makefile için iyi bir test varsa iyidir.
Temel olarak, aşağıdaki gibi bir şey görmek istiyorsunuz:
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
Bu -j
dostça (iyi bir işaret). Kazan plakasını tespit edebilir misiniz? Yazabiliriz:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
aynı etki için (evet, bu biraz daha kompakt hale gelince, önceki formülasyonla aynıdır ).
Komut satırında bir sınır belirleyebilmeniz için parametrelendirmenin bir başka biti ( make
iyi aritmetik makroları olmadığı için sıkıcı , bu yüzden burada hile yapacağım ve kullanacağım $(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Bunu varsayılan olarak 1000 make -j5 LAST=550
ile çalıştırırsınız LAST
.
.PHONY: all
, make adlı bir dosyayı arayacaktır all
. Böyle bir dosya varsa, o zaman dosyanın son değiştirilme zamanını kontrol eder ve makefile neredeyse istediğinizi yapmayacaktır. .PHONY
Deklarasyon markasını söyler all
sembolik bir hedeftir. Bu nedenle Make, all
hedefi daima güncelliğini yitirir. Mükemmel. El kitabına bakın.
%
, kuralda eşleşen her şeyin $*
tarifte olduğu gibi kullanılabilir olması için birini kullanıyorum.
Sorunun birkaç yaşında olduğunu anlıyorum, ancak bu yazı, yukarıdakilerden farklı bir yaklaşım gösterdiğinden ve kabuk işlemlerine veya geliştiricinin sabit kodlanmış bir şemaya gereksinim duymadığından hala birileri için yararlı olabilir. sayısal değerler dizesi.
$ (eval ....) yerleşik makrosu sizin dostunuzdur. Veya en azından olabilir.
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)
Bu basit bir örnek. Büyük değerler için güzel ölçeklenmez - işe yarar, ancak ITERATE_COUNT dizesi her yineleme için 2 karakter (boşluk ve nokta) artacağından, binlere yükseldikçe, kelimeleri saymak giderek daha uzun sürer. Yazıldığı gibi, iç içe yinelemeyi işlemez (bunu yapmak için ayrı bir yineleme işlevine ve sayacına ihtiyacınız olacaktır). Bu tamamen gnu yapmak, hiçbir kabuk gereksinimi (Açıkçası OP her seferinde bir program çalıştırmak istiyordu - burada, sadece bir mesaj gösteriyorum). ITERATE içindeki if değeri 0 değerini yakalamaya yöneliktir, çünkü $ (word ...) aksi halde hata verir.
Sayaç olarak hizmet etmek için büyüyen dize kullanıldığından, $ (kelimeler ...) yerleşiminin arapça bir sayı sağlayabildiğini, ancak bu işlemin matematik işlemlerini başka şekilde desteklemediğini unutmayın (Bir şeye 1 + 1 atayamazsınız ve 2, kabuktan sizin için bir şey çağırmıyorsanız veya eşit derecede kıvrık bir makro işlemi kullanmıyorsanız). Bu bir INCREMENTAL sayaç için harika çalışıyor, ancak bir DECREMENT sayaç için çok iyi değil.
Bunu kendim kullanmıyorum, ancak son zamanlarda, bazı kütüphaneleri eklediğinizde DİĞER kütüphanelere getirmeyi bilmeniz gereken çok ikili, çok kütüphaneli bir yapı ortamında kütüphane bağımlılıklarını değerlendirmek için özyinelemeli bir işlev yazmam gerekiyordu. Kendisinin başka bağımlılıkları vardır (bazıları yapı parametrelerine bağlı olarak değişir) ve yukarıdakine benzer bir $ (eval) ve counter yöntemi kullanıyorum (benim durumumda, sayaç bir şekilde sonsuzluğa girmediğimizden emin olmak için kullanılır döngü ve ayrıca ne kadar yineleme gerektiğini rapor etmek için bir teşhis olarak).
OP'nin Q: $ (eval ...) için önemli olmasa da, hiçbir şeye değmeyecek bir şey, bir değişkenin bir makro türü olduğunda ( =), acil bir atamaya karşı (: ile başlatıldı: =). Bir değişkeni kendi atamasında kullanmak istediğiniz zamanlar vardır ve $ (eval ...) bunu yapmanızı sağlar. Burada dikkate alınması gereken önemli nokta, eval'ü çalıştırdığınızda değişkenin çözülmesidir ve çözülen kısmın artık makro olarak ele alınmamasıdır. Ne yaptığınızı biliyorsanız ve kendisine bir ödevin RHS'sinde bir değişken kullanmaya çalışıyorsanız, bu genellikle yine de olmasını istediğiniz şeydir.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Mutlu olun.
Platformlar arası destek için, komut ayırıcıyı (aynı satırda birden fazla komut yürütmek için) yapılandırılabilir yapın.
Örneğin bir Windows platformunda MinGW kullanıyorsanız komut ayırıcısı &
:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
Bu, birleştirilmiş komutları tek bir satırda yürütür:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
Başka yerlerde de belirtildiği gibi, bir * nix platform kullanımı CMDSEP = ;
.
Bu gerçekten sorunun saf bir cevabı değil, bu tür problemleri çözmek için akıllı bir yol:
karmaşık bir dosya yazmak yerine, örneğin aşağıdaki gibi bir bash betiğine denetim yetkisi verin: makefile
foo : bar.cpp baz.h
bash script.sh
ve script.sh şöyle görünür:
for number in 1 2 3 4
do
./a.out $number
done
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ done all: set_var burada SSA_CORE0_MAINEXEC zaten ayarlanmış bir ortam değişkenidir.Bu yüzden bu değerin var1 değişkeni kullanılarak değerlendirilmesini veya yazdırılmasını istiyorum. Yukarıda gösterildiği gibi denedim ama çalışmıyor. lütfen yardım et.
bash
ve böylece özellikleri kullanabilir. Döngü, bunun gösterilebildiği özelliklerden biridir.
set -e
For-loop için önek olarak kullanabilirsiniz . Misal:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
hemen bir çıkış kodu ile çıkacaktır <> 0
.
GNUmake tablo araç takımının gerçek bir while
döngüsü olmasına rağmen (GNUmake programlamada iki veya üç yürütme aşamasıyla ne anlama gelirse), gerekli olan şey yinelemeli bir listeyse, basit bir çözüm vardır interval
. Eğlenmek için sayıları onaltılık biçime dönüştürüyoruz:
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))
Çıktı:
./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.