जवाबों:
यदि ./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
यह 10 समावेशी के माध्यम से 1 आउटपुट करता है, बस 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
जो संख्याओं का एक क्रम उत्पन्न करता है वह अधिकांश (सभी?) यूनिक्स प्रणालियों पर मौजूद होता है, इसलिए आप लिख सकते हैं for number in ``seq 1 1000``; do echo $$number; done
(seq कमांड के प्रत्येक पक्ष पर एक सिंगल बैकटिक क्लिक करें, दो नहीं, मुझे नहीं पता कि यह कैसे सही तरीके से प्रारूपित करना है
make
आमतौर पर हर लाइन को एक अलग सब-शेल में चलाने की चीज माना जाता है । निरंतरता के बिना, यह for number in 1 2 3 4 ; do
लूप के बाकी हिस्सों के बिना, केवल (उदाहरण के लिए) के साथ एक सबस्क्रिप्शन चलाने की कोशिश करेगा । इसके साथ, यह प्रभावी रूप से प्रपत्र की एक पंक्ति बन जाती है while something ; do something ; done
, जो एक पूर्ण विवरण है। इस $$
सवाल का जवाब यहां दिया गया है: stackoverflow.com/questions/26564825/… , इस बहुत ही उत्तर से निकाले गए कोड के साथ :-)
यदि आप GNU मेक का उपयोग कर रहे हैं, तो आप कोशिश कर सकते हैं
NUMBERS = 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
परवाह किए बिना निष्पादित किया जाएगा।
करने के लिए इस्तेमाल करते हैं IMHO प्रमुख कारण है -j
झंडा। make -j5
एक बार में 5 शेल कमांड चलाएगा। यह अच्छा है अगर आपके पास 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
कि कोई अच्छा अंकगणित मैक्रोज़ नहीं है, इसलिए मैं यहां धोखा दूंगा और उपयोग करूंगा $(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
, मेक नामक एक फाइल की तलाश करेगा all
। यदि ऐसी कोई फ़ाइल मौजूद है, तो उस फ़ाइल के अंतिम-परिवर्तित-समय की जांच करें, और मेकफाइल लगभग निश्चित रूप से वह नहीं करेगा जो आपने इरादा किया था। .PHONY
घोषणा कि मेकअप बताता है all
एक प्रतीकात्मक लक्ष्य है। इसलिए बनाओ 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 वर्णों (स्थान और डॉट) से बढ़ेगा, जैसा कि आप हजारों में उठते हैं, शब्दों को गिनने में उत्तरोत्तर अधिक समय लगता है। जैसा कि लिखा गया है, यह नेस्टेड पुनरावृत्ति को संभालता नहीं है (आपको ऐसा करने के लिए एक अलग पुनरावृत्ति फ़ंक्शन और काउंटर की आवश्यकता होगी)। यह विशुद्ध रूप से ग्नू मेक है, कोई शेल आवश्यकता नहीं है (हालांकि स्पष्ट रूप से ओपी हर बार एक कार्यक्रम चलाने के लिए देख रहा था - यहां, मैं केवल एक संदेश प्रदर्शित कर रहा हूं)। अगर ITERATE के भीतर मान 0 को पकड़ने का इरादा है, क्योंकि $ (शब्द ...) अन्यथा त्रुटि होगी।
ध्यान दें कि काउंटर के रूप में सेवा करने के लिए बढ़ते हुए तार को नियोजित किया जाता है क्योंकि $ (शब्द ...) बिलिन एक अरबी गिनती प्रदान कर सकता है, लेकिन यह अन्यथा गणित के संचालन का समर्थन नहीं करता है (आप 1 + 1 को किसी चीज़ को असाइन नहीं कर सकते हैं और 2 प्राप्त कर सकते हैं) जब तक आप शेल से किसी चीज़ को आपके लिए पूरा करने के लिए, या समान रूप से जटिल मैक्रो ऑपरेशन का उपयोग कर रहे हैं)। हालांकि यह एक काउंटर के लिए बहुत अच्छा काम करता है, लेकिन एक निर्णय के लिए इतना अच्छा नहीं है।
मैं स्वयं इसका उपयोग नहीं करता हूं, लेकिन हाल ही में, मुझे एक बहु-बाइनरी, मल्टी-लाइब्रेरी बिल्ड वातावरण में लाइब्रेरी निर्भरता का मूल्यांकन करने के लिए एक पुनरावर्ती फ़ंक्शन लिखने की आवश्यकता थी, जहां आपको कुछ लाइब्रेरी शामिल करने के लिए अन्य पुस्तकालयों में लाने के लिए जानने की आवश्यकता है अपने आप में अन्य निर्भरताएं हैं (जिनमें से कुछ बिल्ड मापदंडों के आधार पर भिन्न होती हैं), और मैं ऊपर दिए गए समान $ (eval) और काउंटर विधि का उपयोग करता हूं (मेरे मामले में, काउंटर का उपयोग यह सुनिश्चित करने के लिए किया जाता है कि हम किसी तरह अंतहीन में न जाएं लूप, और यह भी एक निदान के रूप में रिपोर्ट करने के लिए कि कितना चलना आवश्यक था)।
ओपी के क्यू: $ (eval ...) के लिए महत्वपूर्ण नहीं है, हालांकि कुछ और लायक है, परिपत्र संदर्भों के लिए आंतरिक घृणा को दरकिनार करने के लिए एक विधि प्रदान करता है, जो एक चर प्रकार के साथ एक गहन प्रकार के साथ लागू करने के लिए अच्छा और ठीक है =), बनाम एक तत्काल असाइनमेंट (=: के साथ प्रारंभ)। कई बार आप अपने स्वयं के असाइनमेंट के भीतर एक चर का उपयोग करने में सक्षम होना चाहते हैं, और $ (eval ...) आपको ऐसा करने में सक्षम करेगा। यहाँ पर विचार करने के लिए महत्वपूर्ण बात यह है कि जिस समय आप निष्कासन चलाते हैं, चर हल हो जाता है, और जो भाग हल हो जाता है वह अब स्थूल के रूप में नहीं माना जाता है। यदि आप जानते हैं कि आप क्या कर रहे हैं और आप अपने आप को असाइनमेंट के आरएचएस पर एक चर का उपयोग करने की कोशिश कर रहे हैं, तो यह आम तौर पर आप वैसे भी होना चाहते हैं।
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))
यह एक पंक्ति में समाप्त आदेशों को कार्यान्वित करता है:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
जैसा कि कहीं और उल्लेख किया गया है, एक * निक्स मंच उपयोग पर CMDSEP = ;
।
यह वास्तव में सवाल का शुद्ध जवाब नहीं है, लेकिन इस तरह की समस्याओं के आसपास काम करने का एक बुद्धिमान तरीका है:
एक जटिल फ़ाइल लिखने के बजाय, उदाहरण के लिए एक बैश स्क्रिप्ट जैसे: मेकफाइल को नियंत्रित करना
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)); सभी किया: set_var यहाँ SSA_CORE0_MAINEXEC एक पर्यावरण चर है जो पहले से ही सेट है। इसलिए मैं चाहता हूं कि वैरिएबल var1 का उपयोग करके मूल्यांकन या मुद्रित हो। मैंने इसे ऊपर दिखाए अनुसार काम नहीं किया था। कृपया मदद कीजिए।
bash
और इस प्रकार सुविधाओं का उपयोग कर सकता है। लूप उन विशेषताओं में से एक है जिनके लिए यह प्रदर्शित किया जा सकता है।
आप set -e
फॉर-लूप के लिए उपसर्ग के रूप में उपयोग कर सकते हैं । उदाहरण:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
एक निकास कोड के साथ तुरंत बाहर निकल जाएगा <> 0
।
यद्यपि GNUmake टेबल टूलकिट में एक सच्चा while
लूप होता है (जो कि GNUmake प्रोग्रामिंग में इसका मतलब है कि इसके दो या तीन चरणों में निष्पादन के साथ), अगर जरूरत वाली चीज एक पुनरावृत्त सूची है, तो इसके साथ एक सरल समाधान है interval
। इसके मज़े के लिए, हम संख्याओं को हेक्स में भी बदलते हैं:
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.