Jawaban:
Berikut ini akan melakukannya jika, seperti yang saya asumsikan dengan penggunaan ./a.out
Anda, Anda berada pada platform tipe UNIX.
for number in 1 2 3 4 ; do \
./a.out $$number ; \
done
Tes sebagai berikut:
target:
for number in 1 2 3 4 ; do \
echo $$number ; \
done
menghasilkan:
1
2
3
4
Untuk rentang yang lebih besar, gunakan:
target:
number=1 ; while [[ $$number -le 10 ]] ; do \
echo $$number ; \
((number = number + 1)) ; \
done
Ini menghasilkan 1 hingga 10 inklusif, hanya mengubah while
kondisi terminating dari 10 menjadi 1000 untuk rentang yang jauh lebih besar seperti yang ditunjukkan dalam komentar Anda.
Loop bersarang dapat dilakukan sebagai berikut:
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
memproduksi:
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
perintah yang menghasilkan urutan angka ada pada sebagian besar (semua?) Sistem unix, sehingga Anda dapat menulis for number in ``seq 1 1000``; do echo $$number; done
(Letakkan backtick tunggal di setiap sisi perintah seq, bukan dua, saya tidak tahu cara memformat ini dengan benar menggunakan sintaks stackoverflow)
make
biasanya memperlakukan setiap baris sebagai sesuatu untuk dijalankan dalam sub-shell yang terpisah . Tanpa kelanjutan, ia akan mencoba menjalankan subshell dengan just (misalnya) for number in 1 2 3 4 ; do
, tanpa sisa dari loop. Dengan itu, ia secara efektif menjadi satu baris bentuk while something ; do something ; done
, yang merupakan pernyataan lengkap. The $$
Pertanyaan dijawab di sini: stackoverflow.com/questions/26564825/... , dengan kode yang tampaknya diambil dari sangat jawaban ini :-)
Jika Anda menggunakan GNU make, Anda bisa mencoba
NOMOR = 1 2 3 4 lakukan: $ (foreach var, $ (NUMBERS),. / a.out $ (var);)
yang akan menghasilkan dan mengeksekusi
./a.out 1; ./a.out 2; ./a.out 3; ./a.out 4;
./a.out 1
. ./a.out 2
akan dieksekusi bagaimanapun juga.
THE alasan utama untuk menggunakan make IMHO adalah -j
bendera. make -j5
akan menjalankan 5 perintah shell sekaligus. Ini bagus jika Anda memiliki 4 CPU katakan, dan tes yang baik dari makefile apa pun.
Pada dasarnya, Anda ingin melihat sesuatu seperti:
.PHONY: all
all: job1 job2 job3
.PHONY: job1
job1: ; ./a.out 1
.PHONY: job2
job2: ; ./a.out 2
.PHONY: job3
job3: ; ./a.out 3
Ini -j
ramah (pertanda baik). Bisakah Anda melihat pelat-ketel? Kita bisa menulis:
.PHONY: all job1 job2 job3
all: job1 job2 job3
job1 job2 job3: job%:
./a.out $*
untuk efek yang sama (ya, ini adalah sama dengan formulasi sebelumnya sejauh make yang bersangkutan, hanya sedikit lebih kompak).
Sedikit parameterisasi lebih lanjut sehingga Anda dapat menentukan batas pada command-line (membosankan karena make
tidak memiliki makro aritmatika yang baik, jadi saya akan menipu di sini dan menggunakan $(shell ...)
)
LAST := 1000
NUMBERS := $(shell seq 1 ${LAST})
JOBS := $(addprefix job,${NUMBERS})
.PHONY: all ${JOBS}
all: ${JOBS} ; echo "$@ success"
${JOBS}: job%: ; ./a.out $*
Anda menjalankan ini dengan make -j5 LAST=550
, dengan LAST
default ke 1000.
.PHONY: all
, make akan mencari file bernama all
. Jika ada file seperti itu, buat lalu periksa file itu terakhir kali berubah, dan makefile hampir pasti tidak akan melakukan apa yang Anda inginkan. The .PHONY
deklarasi mengatakan make yang all
merupakan target simbolis. Karenanya, Make akan mempertimbangkan all
target untuk selalu ketinggalan zaman. Sempurna. Lihat manualnya.
%
dengan aturan tersebut tersedia seperti $*
dalam resep.
Saya menyadari pertanyaannya sudah berumur beberapa tahun, tetapi postingan ini mungkin masih bermanfaat bagi seseorang karena menunjukkan pendekatan yang berbeda dari yang di atas, dan tidak bergantung pada operasi shell maupun kebutuhan pengembang untuk membuat hardcoded. string nilai numerik.
makro builtin $ (eval ....) adalah teman Anda. Atau setidaknya bisa.
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)
Itu contoh sederhana. Ini tidak akan menskala cantik untuk nilai besar - itu berfungsi, tetapi karena string ITERATE_COUNT akan meningkat sebesar 2 karakter (spasi dan titik) untuk setiap iterasi, saat Anda mencapai ribuan, semakin lama semakin dibutuhkan untuk menghitung kata-kata. Seperti yang ditulis, itu tidak menangani iterasi bersarang (Anda akan memerlukan fungsi iterasi terpisah dan counter untuk melakukannya). Ini murni gnu make, tidak ada persyaratan shell (meskipun jelas OP sedang mencari untuk menjalankan program setiap kali - di sini, saya hanya menampilkan pesan). Jika dalam ITERATE dimaksudkan untuk menangkap nilai 0, karena $ (kata ...) akan kesalahan keluar sebaliknya.
Perhatikan bahwa string yang berkembang untuk berfungsi sebagai penghitung digunakan karena $ (kata-kata ...) builtin dapat memberikan hitungan arab, tetapi yang membuatnya tidak mendukung operasi matematika (Anda tidak dapat menetapkan 1 +1 ke sesuatu dan mendapatkan 2, kecuali jika Anda meminta sesuatu dari shell untuk menyelesaikannya untuk Anda, atau menggunakan operasi makro yang sama berbelit-belit). Ini bekerja sangat baik untuk penghitung INCREMENTAL, namun tidak begitu baik untuk penghitungan DECREMENT.
Saya tidak menggunakan ini sendiri, tetapi baru-baru ini, saya harus menulis fungsi rekursif untuk mengevaluasi dependensi perpustakaan di multi-biner, multi-perpustakaan membangun lingkungan di mana Anda perlu tahu untuk membawa perpustakaan LAIN ketika Anda memasukkan beberapa perpustakaan yang itu sendiri memiliki dependensi lain (beberapa di antaranya bervariasi tergantung pada parameter build), dan saya menggunakan $ (eval) dan metode penghitung yang mirip dengan di atas (dalam kasus saya, penghitung digunakan untuk memastikan kita tidak entah bagaimana masuk ke yang tak berujung loop, dan juga sebagai diagnostik untuk melaporkan berapa banyak iterasi diperlukan).
Sesuatu yang lain tidak bernilai apa pun, meskipun tidak signifikan untuk OP's Q: $ (eval ...) menyediakan metode untuk menghindari kebencian internal make terhadap referensi melingkar, yang semuanya baik dan baik untuk ditegakkan ketika variabel adalah tipe makro (diinternalisasi dengan =), versus penugasan langsung (diinisialisasi dengan: =). Ada saat-saat Anda ingin dapat menggunakan variabel dalam tugasnya sendiri, dan $ (eval ...) akan memungkinkan Anda untuk melakukan itu. Hal penting yang perlu dipertimbangkan di sini adalah bahwa pada saat Anda menjalankan eval, variabel diselesaikan, dan bagian yang diselesaikan tidak lagi diperlakukan sebagai makro. Jika Anda tahu apa yang Anda lakukan dan Anda mencoba menggunakan variabel pada RHS dari sebuah tugas untuk dirinya sendiri, ini umumnya adalah apa yang ingin Anda lakukan.
SOMESTRING = foo
# will error. Comment out and re-run
SOMESTRING = pre-${SOMESTRING}
# works
$(eval SOMESTRING = pre${SOMESTRING}
default:
@echo ${SOMESTRING}
Selamat bercinta.
Untuk dukungan lintas-platform, buat pemisah perintah (untuk menjalankan beberapa perintah pada baris yang sama) dapat dikonfigurasi.
Misalnya, jika Anda menggunakan MinGW pada platform Windows, pemisah perintah adalah &
:
NUMBERS = 1 2 3 4
CMDSEP = &
doit:
$(foreach number,$(NUMBERS),./a.out $(number) $(CMDSEP))
Ini mengeksekusi perintah gabungan dalam satu baris:
./a.out 1 & ./a.out 2 & ./a.out 3 & ./a.out 4 &
Seperti disebutkan di tempat lain, pada platform * nix digunakan CMDSEP = ;
.
Ini sebenarnya bukan jawaban murni untuk pertanyaan, tetapi cara cerdas untuk mengatasi masalah seperti:
alih-alih menulis file yang kompleks, cukup mendelegasikan kontrol misalnya skrip bash seperti: makefile
foo : bar.cpp baz.h
bash script.sh
dan script.sh terlihat seperti:
for number in 1 2 3 4
do
./a.out $number
done
eval echo \$${$(var)}
; \ echo $$ var1; \ ((NUM = NUM + 1)); \ selesai semua: set_var di sini SSA_CORE0_MAINEXEC adalah variabel lingkungan yang sudah ditetapkan. Jadi saya ingin nilai itu dievaluasi atau dicetak menggunakan variabel var1. Saya mencobanya seperti yang ditunjukkan di atas tetapi tidak berhasil. tolong bantu.
bash
dan dengan demikian menggunakan fitur-fiturnya. Loop adalah salah satu fitur yang dapat ditunjukkan.
Anda dapat menggunakan set -e
awalan untuk for-loop. Contoh:
all:
set -e; for a in 1 2 3; do /bin/false; echo $$a; done
make
akan segera keluar dengan kode keluar <> 0
.
Meskipun toolkit tabel GNUmake memiliki while
loop yang benar (apa pun artinya dalam pemrograman GNUmake dengan dua atau tiga fase eksekusi), jika hal yang diperlukan adalah daftar berulang, ada solusi sederhana dengan interval
. Untuk bersenang-senang, kami mengonversi angka menjadi hex juga:
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))
Keluaran:
./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.