Berikut ini akan melakukannya jika, seperti yang saya asumsikan dengan penggunaan ./a.outAnda, 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 whilekondisi terminating dari 10 menjadi 1000 untuk rentang yang jauh lebih besar seperti yang ditunjukkan dalam komentar Anda.
qwert hanyalah nama target yang tidak mungkin berupa file asli. Aturan makefile membutuhkan target. Adapun kesalahan sintaksis, Anda kehilangan beberapa hal - lihat pembaruan.
paxdiablo
2
Karena Anda mengasumsikan shellnya mengenali ((...)), mengapa tidak menggunakan yang lebih sederhana untuk ((i = 0; i <WHATEVER; ++ i)); lakukan ...; selesai?
Idelic
1
Perhatikan bahwa seqperintah 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)
Suzanne Dupéron
3
Terima kasih, saya kehilangan $$ ganda untuk referensi variabel loop.
Leif Gruenwoldt
1
@ Jonz: karakter kelanjutan garis karena makebiasanya 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 :-)
paxdiablo
265
Jika Anda menggunakan GNU make, Anda bisa mencoba
NOMOR = 1 2 3 4
lakukan:
$ (foreach var, $ (NUMBERS),. / a.out $ (var);)
Jawaban ini IMHO lebih baik, karena tidak perlu menggunakan shell, itu makefile murni (bahkan jika itu GNU-spesifik).
Jocelyn delalande
7
titik koma sangat penting jika tidak hanya iterasi pertama yang akan dieksekusi
Jeremy Leipzig
7
Solusi ini menyembunyikan kode keluar dari ./a.out 1. ./a.out 2akan dieksekusi bagaimanapun juga.
bobbogo
1
@Alexander: bisakah Anda menguraikan batasan apa yang Anda maksud?
Idelic
1
@ Idelic, ya. Untuk makefile dan shellscript berikut, shellscript berfungsi (meneruskan argumen ke ls), sedangkan Makefile memberikan kesalahan: make: execvp: / bin / sh: Daftar argumen terlalu panjang Makefile: ix.io/d5L Shellscript: ix.io / d5M Ini adalah masalah dalam fungsi foreach yang saya temui di tempat kerja, ketika daftar panjang nama file (dengan jalur panjang juga) diteruskan ke sebuah perintah. Kami harus mencari solusinya.
Alexander
107
THE alasan utama untuk menggunakan make IMHO adalah -jbendera. make -j5akan 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:
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 maketidak 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 LASTdefault ke 1000.
Ini jelas merupakan jawaban terbaik, untuk alasan yang disebutkan bobbogo ( -j ).
dbn
Adakah alasan khusus ini menggunakan akhiran .PHONY? Apakah mereka diharuskan untuk apa saja?
Seb
6
@seb: Tanpa .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 .PHONYdeklarasi mengatakan make yang allmerupakan target simbolis. Karenanya, Make akan mempertimbangkan alltarget untuk selalu ketinggalan zaman. Sempurna. Lihat manualnya.
@ Joe gnu.org/software/make/manual/make.html#Static-Pattern (saya pikir maksud Anda adalah apa * * titik dua * untuk ). Jangan membingungkan mereka dengan Aturan Pola (IMHO) yang tidak baik . Aturan pola statis benar-benar berguna setiap kali daftar target dapat dicocokkan dengan salah satu pola noddy make (sama berlaku untuk dependensi). Di sini saya menggunakan satu hanya untuk kenyamanan bahwa apa pun yang cocok %dengan aturan tersebut tersedia seperti $*dalam resep.
bobbogo
22
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.
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}
Saya terjebak pada langkah saat menulis Makefile. Saya memiliki kode berikut: set_var: @ NUM = 0; sementara [[$$ NUM <1]]; do \ echo "I am here"; \ echo $$ NUM dump $$ {NUM} .txt; \ var = "SSA_CORE $$ {NUM} _MAINEXEC"; \ echo $$ var; \ var1 = 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.
XYZ_Linux
2
Ini memang solusi yang mudah, namun hal ini membuat Anda tidak menggunakan opsi "make -j 4" yang bagus untuk menjalankan proses secara paralel.
TabeaKischka
1
@ TabeaKischka: memang. Itu bukan cara yang " direkomendasikan ", tetapi lebih dimaksudkan jika seseorang membutuhkan beberapa fitur yang tidak ditawarkan oleh Makefile, maka seseorang dapat mundur ke implementasi bashdan dengan demikian menggunakan fitur-fiturnya. Loop adalah salah satu fitur yang dapat ditunjukkan.
Meskipun toolkit tabel GNUmake memiliki whileloop 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))
#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.
Jawaban:
Berikut ini akan melakukannya jika, seperti yang saya asumsikan dengan penggunaan
./a.out
Anda, Anda berada pada platform tipe UNIX.Tes sebagai berikut:
menghasilkan:
Untuk rentang yang lebih besar, gunakan:
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:
memproduksi:
sumber
seq
perintah yang menghasilkan urutan angka ada pada sebagian besar (semua?) Sistem unix, sehingga Anda dapat menulisfor 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 bentukwhile 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
yang akan menghasilkan dan mengeksekusi
sumber
./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:
Ini
-j
ramah (pertanda baik). Bisakah Anda melihat pelat-ketel? Kita bisa menulis: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 ...)
)Anda menjalankan ini dengan
make -j5 LAST=550
, denganLAST
default ke 1000.sumber
.PHONY: all
, make akan mencari file bernamaall
. 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 yangall
merupakan target simbolis. Karenanya, Make akan mempertimbangkanall
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.
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.
Selamat bercinta.
sumber
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
&
:Ini mengeksekusi perintah gabungan dalam satu baris:
Seperti disebutkan di tempat lain, pada platform * nix digunakan
CMDSEP = ;
.sumber
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
dan script.sh terlihat seperti:
sumber
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.Mungkin Anda bisa menggunakan:
sumber
Anda dapat menggunakan
set -e
awalan untuk for-loop. Contoh:make
akan segera keluar dengan kode keluar<> 0
.sumber
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 denganinterval
. Untuk bersenang-senang, kami mengonversi angka menjadi hex juga:Keluaran:
sumber
Solusi makro murni, shell / platform-independent, murni adalah ...
sumber
sumber