Câu trả lời:
Những điều sau đây sẽ làm điều đó nếu, như tôi giả sử khi bạn sử dụng ./a.out
, bạn đang ở trên nền tảng loại UNIX.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Kiểm tra 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 phạm vi lớn hơn, sử dụng:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Điều này bao gồm 1 đến 10, chỉ cần thay đổi while
điều kiện kết thúc từ 10 thành 1000 cho phạm vi lớn hơn nhiều như được nêu trong nhận xét của bạn.
Các vòng lặp lồng nhau có thể được thực hiện như vậy:
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
seq
lệnh tạo ra một chuỗi số tồn tại trên hầu hết các hệ thống unix (tất cả?), Vì vậy bạn có thể viết for number in ``seq 1 1000``; do echo $$number; done
(Đặt một backtick vào mỗi bên của lệnh seq, không phải hai, tôi không biết cách định dạng chính xác sử dụng cú pháp của stackoverflow)
make
thông thường coi mỗi dòng là một thứ để chạy trong một vỏ con riêng biệt . Nếu không tiếp tục, nó sẽ cố chạy một subshell chỉ bằng (ví dụ) for number in 1 2 3 4 ; do
, mà không có phần còn lại của vòng lặp. Với nó, nó thực sự trở thành một dòng duy nhất của biểu mẫu while something ; do something ; done
, đó là một tuyên bố hoàn chỉnh. Câu $$
hỏi được trả lời tại đây: stackoverflow.com/questions/26564825/ , với mã dường như được trích xuất từ chính câu trả lời này :-)
Nếu bạn đang sử dụng GNU, bạn có thể thử
SỐ = 1 2 3 4 làm đi: $ (foreach var, $ (NUMBERS) ,. / a.out $ (var);)
cái sẽ tạo và thực thi
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
./a.out 1
. ./a.out 2
sẽ được thực hiện bất kể.
THE lý do chính để sử dụng làm IMHO là -j
cờ. 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 bài kiểm tra tốt về bất kỳ makefile nào.
Về cơ bản, bạn muốn thực hiện để xem một cái gì đó 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 nồi hơi? Chúng tôi 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 càng xa càng làm cho là có liên quan, nhỏ gọn hơn chỉ là một chút).
Thêm một chút tham số hóa để bạn có thể chỉ định giới hạn cho dòng lệnh (tẻ nhạt vì make
không có bất kỳ macro số học tốt nào, vì vậy tôi sẽ gian lận ở đây và sử dụng $(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Bạn chạy cái này với make -j5 LAST=550
, LAST
mặc định là 1000.
.PHONY: all
, make sẽ tìm một tập tin gọi là all
. Nếu một tệp như vậy tồn tại, hãy thực hiện kiểm tra lần thay đổi cuối cùng của tệp đó và tệp thực hiện gần như chắc chắn sẽ không làm những gì bạn dự định. Các .PHONY
tuyên bố nói rằng làm all
là một mục tiêu mang tính biểu tượng. Do đó, Make sẽ xem xét all
mục tiêu luôn luôn lỗi thời. Hoàn hảo. Xem hướng dẫn.
%
quy tắc có sẵn như $*
trong công thức.
Tôi nhận ra câu hỏi đã được vài năm tuổi, nhưng bài đăng này vẫn có thể được sử dụng cho một người nào đó 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 các hoạt động vỏ cũng như không cần nhà phát triển tìm ra mã hóa cứng chuỗi các giá trị số.
macro dựng sẵn $ (eval ....) là bạn của bạn. Hoặc có thể ít nhất.
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 quy mô cho các giá trị lớn - nó hoạt động, nhưng vì 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, khi bạn lên đến hàng nghìn, sẽ mất nhiều thời gian hơn để đếm từ. Như đã viết, nó không xử lý phép lặp lồng nhau (bạn cần một hàm lặp và bộ đếm riêng biệt để làm như vậy). Đây hoàn toàn là một yêu cầu hoàn hảo, không yêu cầu hệ vỏ (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, vì $ (từ ...) sẽ lỗi khác.
Lưu ý rằng chuỗi tăng trưởng để phục vụ như một bộ đếm được sử dụng vì tích hợp $ (từ ...) có thể cung cấp số đếm tiếng Ả Rập, nhưng điều đó không hỗ trợ các hoạt động toán học (Bạn không thể gán 1 + 1 cho thứ gì đó và nhận 2, trừ khi bạn 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 thao tác macro phức tạp như nhau). Điều này hoạt động rất tốt cho một bộ đếm TĂNG CƯỜNG, tuy nhiên không tốt cho một bộ KHAI THÁC.
Tôi không sử dụng cái này cho mình, nhưng gần đây, tôi cần phải viết một hàm đệ quy để đánh giá các phụ thuộc thư viện trên một môi trường xây dựng đa thư viện, đa nhị phân, nơi bạn cần biết để đưa vào các thư viện KHÁC khi bạn bao gồm một số thư viện bản thân nó có các phụ thuộc khác (một số thay đổi tùy thuộc vào tham số xây dựng) và tôi sử dụng phương thức $ (eval) và bộ đếm 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 ta không đi vào vô tận vòng lặp, và cũng như một chẩn đoán để báo cáo số lần lặp là cần thiết).
Một cái gì đó không có giá trị gì, mặc dù không có ý nghĩa đối với Q: $ (eval ...) của OP cung cấp một phương pháp để tránh sự ghê tởm nội bộ đối với các tham chiếu vòng tròn, tất cả đều tốt và tốt để thực thi khi một biến là một loại macro (được định nghĩa bằng =), so với một nhiệm vụ ngay lập tức (khởi tạo với: =). Đôi khi bạn muốn có thể sử dụng một biến trong phép gán riêng của 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ế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 bài tập cho chính nó, thì đây thường là những gì bạn muốn xảy ra.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Chúc mừng
Để hỗ trợ đa nền tảng, hãy phân tách lệnh (để thực thi nhiều lệnh trên cùng một dòng).
Ví dụ: nếu bạn đang sử dụng MinGW trên nền tảng Windows, thì dấu phân cách lệnh là &
:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
Điều này thực thi các lệnh được nối trong một dòng:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
Như đã đề cập ở nơi khác, trên nền tảng * nix sử dụng CMDSEP = ;
.
Đây thực sự không phải là một câu trả lời thuần túy cho câu hỏi, mà là một cách thông minh để giải quyết những vấn đề như vậy:
thay vì viết một tệp phức tạp, chỉ cần ủy quyền kiểm soát ví dụ tập lệnh 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
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ xong tất cả: set_var ở đây SSA_CORE0_MAINEXEC là một biến môi trường đã được đặt. Vì vậy, tôi muốn giá trị đó được đánh giá hoặc in bằng biến var1. Tôi đã thử nó như hình trên nhưng không hoạt động. xin vui lòng giúp đỡ.
bash
và do đó sử dụng các tính năng. Vòng lặp là một trong những tính năng mà điều này có thể được chứng minh.
Bạn có thể sử dụng set -e
làm tiền tố cho vòng lặp for. Thí dụ:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
sẽ thoát ngay lập tức với mã thoát <> 0
.
Mặc dù bộ công cụ bảng GNUmake có một while
vòng lặp thực (bất cứ điều gì có nghĩa là trong lập trình GNUmake với hai hoặc ba giai đoạn thực hiện của nó), nếu điều cần thiết là một danh sách lặp, có một giải pháp đơn giản với interval
. Để giải trí, chúng tôi cũng chuyển đổi các số thành hex:
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))
Đầu ra:
./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.