2009-09-29 57 views

Trả lời

196

Sau đây sẽ làm điều đó nếu, như tôi giả định bởi việc bạn sử dụng ./a.out, bạn đang ở trên nền tảng kiểu UNIX.

for number in 1 2 3 4 ; do \ 
    ./a.out $$number ; \ 
done 

thử nghiệm như sau:

target: 
    for number in 1 2 3 4 ; do \ 
     echo $$number ; \ 
    done 

sản xuất:

1 
2 
3 
4 

Đối với các khoảng lớn hơn, sử dụng:

target: 
    number=1 ; while [[ $$number -le 10 ]] ; do \ 
     echo $$number ; \ 
     ((number = number + 1)) ; \ 
    done 

này kết quả đầu ra từ 1 đến 10, bao gồm, chỉ cần thay đổi while chấm dứt điều kiện từ 10 đến 1000 cho phạm vi lớn hơn nhiều như được nêu trong nhận xét của bạn.

Nested vòng có thể được thực hiện như sau:

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 

sản xuất:

1 1 
1 2 
1 3 
2 1 
2 2 
2 3 
3 1 
3 2 
3 3 
4 1 
4 2 
4 3 
+0

Nhưng nếu tôi muốn lên tới 1000, thì chúng tôi có thể xác định giới hạn không? – avd

+0

Tại sao có, bạn có thể :-) Xem cập nhật của tôi. – paxdiablo

+0

Một điều là sử dụng nhãn qwert là gì? Điều khác là vòng lặp lồng nhau. Nó hiển thị lỗi cú pháp trong số này cho n1 trong 0 1 2; do \ cho n2 trong 1 2 3; do \ ./a.out $$ n1 $$ n2; \ thực hiện thực hiện – avd

204

Nếu bạn đang sử dụng GNU thực hiện, bạn có thể thử

 
NUMBERS = 1 2 3 4 
doit: 
     $(foreach var,$(NUMBERS),./a.out $(var);) 

mà sẽ tạo ra và thực hiện

 
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4; 
+17

Câu trả lời này là IMHO tốt hơn, vì nó không yêu cầu phải sử dụng bất kỳ trình bao nào, đó là makefile thuần túy (ngay cả khi nó là GNU cụ thể). –

+2

Tôi đồng ý, @Jocelyn, đây chắc chắn là câu trả lời hay hơn. – cvk

+5

dấu chấm phẩy là rất quan trọng nếu không chỉ lần lặp đầu tiên sẽ thực thi –

81

THE lý do chính để sử dụng làm IMHO là cờ -j. make -j5 sẽ chạy 5 lệnh shell cùng một lúc. Điều này là tốt nếu bạn có 4 CPU nói, và một thử nghiệm tốt của bất kỳ makefile.

Về cơ bản, bạn muốn làm một cái gì đó để xem như:

.PHONY: all 
all: job1 job2 job3 

.PHONY: job1 
job1: ; ./a.out 1 

.PHONY: job2 
job2: ; ./a.out 2 

.PHONY: job3 
job3: ; ./a.out 3 

Đây là -j thân thiện (một dấu hiệu tốt). Bạn có thể nhận ra tấm lò hơi không? Chúng ta có thể viết:

.PHONY: all job1 job2 job3 
all: job1 job2 job3 
job1 job2 job3: job%: 
    ./a.out $* 

cho tác dụng tương tự (có, điều này cũng giống như việc xây dựng trước đó như xa như làm là có liên quan, nhỏ gọn hơn chỉ là một chút).

Một chút nữa của parameterisation để bạn có thể chỉ định một giới hạn về dòng lệnh (tẻ nhạt như make không có bất kỳ macro số học tốt, vì vậy tôi sẽ lừa dối ở đây và sử dụng $(shell ...))

LAST := 1000 
NUMBERS := $(shell seq 1 ${LAST}) 
JOBS := $(addprefix job,${NUMBERS}) 
.PHONY: all ${JOBS} 
all: ${JOBS} ; echo "[email protected] success" 
${JOBS}: job%: ; ./a.out $* 

Bạn chạy điều này với make -j5 LAST=550, với LAST đặt mặc định là 1000.

+7

Đây chắc chắn là câu trả lời hay nhất, vì lý do mà bobbogo được đề cập (_-j_). – dbn

+0

Bất kỳ lý do cụ thể nào đều sử dụng các hậu tố PHONY? Họ có cần gì không? – Seb

+5

@seb: Không có '.PHONY: all', make sẽ tìm kiếm một tệp có tên là' all'. Nếu một tệp như vậy tồn tại, hãy kiểm tra xem tệp đã thay đổi lần cuối của tệp đó và makefile sẽ gần như chắc chắn không làm những gì bạn dự định. Tuyên bố '.PHONY' cho biết rằng' all' là một mục tiêu tượng trưng. Do đó, hãy xem xét mục tiêu 'tất cả' luôn luôn lỗi thời. Hoàn hảo. Xem hướng dẫn sử dụng. – bobbogo

14

Để có hỗ trợ đa nền tảng, hãy đặt cấu hình lệnh (để thực thi nhiều lệnh trên cùng một dòng).

Nếu bạn đang sử dụng MinGW trên nền tảng Windows ví dụ, tách lệnh là &:

NUMBERS = 1 2 3 4 
CMDSEP = & 
doit: 
    $(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP)) 

này thực thi các lệnh nối trong một dòng:

./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 & 

Như đã đề cập ở những nơi khác, trên nền tảng * nix sử dụng CMDSEP = ;.

+0

và hoạt động trên unix quá. – orkoden

18

Tôi nhận ra câu hỏi là vài năm, nhưng bài đăng này vẫn có thể được sử dụng cho ai đó vì nó thể hiện một cách tiếp cận khác với ở trên và không phụ thuộc vào hoạt động của vỏ hoặc cũng không cần nhà phát triển schpeel ra một chuỗi hardcoded các giá trị số.

macro dựng sẵn $ (eval ....) là bạn của bạn. Hoặc ít nhất cũng có thể.

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) 

Đó là một ví dụ đơn giản. Nó sẽ không mở rộng cho các giá trị lớn - nó hoạt động, nhưng khi chuỗi ITERATE_COUNT sẽ tăng thêm 2 ký tự (dấu cách và dấu chấm) cho mỗi lần lặp lại, khi bạn nhận được vào hàng nghìn, phải mất dần dần để đếm các từ. Như được viết, nó không xử lý lặp lồng nhau (bạn cần một hàm lặp riêng biệt và truy cập để làm như vậy). Đây hoàn toàn là gnu, không yêu cầu shell (mặc dù rõ ràng OP đang tìm cách chạy một chương trình mỗi lần - ở đây, tôi chỉ hiển thị một thông báo). Nếu trong ITERATE được dự định bắt giá trị 0, bởi vì $ (từ ...) sẽ bị lỗi nếu không. Lưu ý rằng chuỗi ngày càng tăng để phục vụ như một bộ đếm được sử dụng bởi vì $ (words ...) nội trang có thể cung cấp số lượng arabic, nhưng điều đó không hỗ trợ hoạt động toán học (Bạn không thể gán 1 + 1 cho một cái gì đó và nhận được 2, trừ khi bạn đang gọi một cái gì đó từ trình bao để hoàn thành nó cho bạn, hoặc sử dụng một hoạt động macro phức tạp). Điều này làm việc tuyệt vời cho một truy cập INCREMENTAL, không quá tốt cho một DECREMENT một tuy nhiên.

Tôi không tự mình sử dụng, nhưng gần đây, tôi cần phải viết hàm đệ quy để đánh giá phụ thuộc thư viện trên môi trường đa nhị phân, đa thư viện mà bạn cần biết để mang thư viện KHÁC khi bạn bao gồm một số thư viện có các phụ thuộc khác (một số khác nhau tùy thuộc vào các tham số xây dựng) và tôi sử dụng phương thức $ (eval) và truy cập tương tự như ở trên (trong trường hợp của tôi, bộ đếm được sử dụng để đảm bảo chúng tôi không bằng cách nào đó đi vào một vòng lặp vô tận, và cũng như một chẩn đoán để báo cáo bao nhiêu lần lặp lại là cần thiết).

Điều gì đó không đáng kể, mặc dù không quan trọng đối với Q: $ (eval ...) cung cấp một phương pháp để phá vỡ sự thất vọng nội bộ của đối với tham chiếu vòng tròn, tất cả đều tốt và tốt để thực thi khi biến là macro type (intialized with =), so với gán ngay lập tức (được khởi tạo với: =). Có những lúc bạn muốn có thể sử dụng một biến trong nhiệm vụ của chính nó, và $ (eval ...) sẽ cho phép bạn làm điều đó. Điều quan trọng cần xem xét ở đây là tại thời điểm bạn chạy eval, biến được giải quyết và phần đó được giải quyết không còn được coi là macro nữa. Nếu bạn biết những gì bạn đang làm và bạn đang cố gắng sử dụng một biến trên RHS của một nhiệm vụ cho chính nó, điều này thường là những gì bạn muốn xảy ra anyway.

SOMESTRING = foo 

    # will error. Comment out and re-run 
    SOMESTRING = pre-${SOMESTRING} 

    # works 
    $(eval SOMESTRING = pre${SOMESTRING} 

default: 
    @echo ${SOMESTRING} 

Chúc mừng make'ing.

3

Đây không phải là thực sự là một câu trả lời tinh khiết cho câu hỏi, nhưng một cách thông minh để làm việc xung quanh vấn đề như vậy:

thay vì viết một tập tin phức tạp, chỉ cần ủy quyền kiểm soát để ví dụ một kịch bản bash như: makefile

foo : bar.cpp baz.h 
    bash script.sh 

và script.sh trông giống như:

for number in 1 2 3 4 
do 
    ./a.out $number 
done 
+0

Tôi đã bị kẹt ở một bước trong khi viết một Makefile. Tôi có mã sau: set_var: @ NUM = 0; trong khi [[$$ NUM <1]]; làm \ echo "Tôi ở đây"; \ echo $$ NUM dump $$ {NUM} .txt; \ var = "SSA_CORE $$ {NUM} _MAINEXEC"; \ echo $$ var; \ var1 = 'eval echo \ $$ {$ (var)}'; \ echo $$ var1; \ ((NUM = NUM ​​+ 1)); \ thực hiện tất cả: set_var tại đây SSA_CORE0_MAINEXEC là một biến môi trường đã được thiết lập. Tôi muốn giá trị đó được đánh giá hoặc in bằng biến var1. Tôi đã thử nó như được hiển thị ở trên nhưng không hoạt động. Hãy giúp tôi. –

3

lẽ bạn có thể sử dụng:

xxx: 
    for i in `seq 1 4`; do ./a.out $$i; done; 
+0

không, không thể :-( – zx1986

0
#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. 
1

Bạn có thể sử dụng set -e làm tiền tố cho vòng lặp. Ví dụ:

all: 
    set -e; for a in 1 2 3; do /bin/false; echo $$a; done 

sẽ thoát ngay lập tức với mã thoát <> 0.

Các vấn đề liên quan