Saya mencoba menjalankan dua urutan dalam loop yang sama di shell saya seperti di bawah ini:
#!/bin/bash
for i in (1..15) and (20..25) ;
do
echo $i
......
.....other process
done
ada ide bagaimana saya bisa mencapai ini?
Saya mencoba menjalankan dua urutan dalam loop yang sama di shell saya seperti di bawah ini:
#!/bin/bash
for i in (1..15) and (20..25) ;
do
echo $i
......
.....other process
done
ada ide bagaimana saya bisa mencapai ini?
Jawaban:
Anda hanya perlu ekspansi penjepit untuk itu
$ for n in {1..3} {200..203}; do echo $n; done
1
2
3
200
201
202
203
Kami dapat meneruskan daftar ke for
( ).for i in x y z; do stuff "$i"; done
Jadi di sini, kawat gigi {
}
mendapatkan shell untuk memperluas urutan Anda ke dalam daftar. Anda hanya perlu menempatkan spasi di antara mereka, karena shell membagi daftar argumen pada mereka.
echo
nomor
touch
file, mereka bisa melakukannya touch {1..15}.txt {20..25}.txt
, tidak perlu loop di sini. Tapi tentu saja jika beberapa tindakan pada nomor yang sama - OK, itu bisa menggunakan perulangan.
Atau kita dapat menggunakan seq
( mencetak urutan angka ), berikut adalah dua contoh yang setara:
for i in `seq 1 3` `seq 101 103`; do echo $i; done
for i in $(seq 1 3) $(seq 101 103); do echo $i; done
Jika ini adalah skrip, untuk tugas berulang, Anda dapat menggunakan fungsi:
#!/bin/bash
my_function() { echo "$1"; }
for i in {1..3}; do my_function "$i"; done
for i in {101..103}; do my_function "$i"; done
#!/bin/bash
my_function() { for i in `seq $1 $2`; do echo "$i"; done; }
my_function "1" "3"
my_function "101" "103"
Jawaban Zanna dan jawaban pa4080 sama-sama baik dan saya mungkin akan pergi dengan salah satu dari mereka dalam banyak situasi. Mungkin tidak perlu dikatakan lagi, tetapi demi kelengkapan, saya tetap akan mengatakannya: Anda dapat memuat setiap nilai ke dalam array dan kemudian mengulangi array. Sebagai contoh:
the_array=( 1 2 3 4 5 6 7 8 9 10 20 21 22 23 24 25 )
for i in "${the_array[@]}";
do
echo $i
done
Jawaban Zanna benar-benar benar dan cocok untuk bash, tetapi kita dapat meningkatkannya lebih banyak lagi tanpa menggunakan loop.
printf "%d\n" {1..15} {20..25}
Perilaku printf
adalah sedemikian rupa sehingga jika jumlah ARGUMENTS
lebih besar dari kontrol format 'FORMAT STRING'
, maka printf
akan membagi semua ARGUMENTS
menjadi potongan yang sama dan terus menyesuaikan mereka ke string format berulang-ulang sampai kehabisan ARGUMENTS
daftar.
Jika kita berjuang untuk portabilitas, kita dapat memanfaatkan printf "%d\n" $(seq 1 15) $(seq 20 25)
sebagai gantinya
Mari kita lanjutkan ini dan lebih menyenangkan. Katakanlah kita ingin melakukan tindakan daripada hanya mencetak angka. Untuk membuat file dari urutan angka itu, kita bisa dengan mudah melakukannya touch {1..15}.txt {20..25}.txt
. Bagaimana jika kita ingin banyak hal terjadi? Kita juga bisa melakukan sesuatu seperti ini:
$ printf "%d\n" {1..15} {20..25} | xargs -I % bash -c 'touch "$1.txt"; stat "$1.txt"' sh %
Atau jika kita ingin menjadikannya gaya sekolah lama:
printf "%d\n" {1..15} {20..25} | while read -r line; do
touch "$line".txt;
stat "$line".txt;
rm "$line".txt;
done
Jika kita ingin membuat solusi skrip yang bekerja dengan shell yang tidak memiliki ekspansi brace (yang {1..15} {20..25}
bergantung pada), kita dapat menulis loop sementara sederhana:
#!/bin/sh
start=$1
jump=$2
new_start=$3
end=$4
i=$start
while [ $i -le $jump ]
do
printf "%d\n" "$i"
i=$((i+1))
if [ $i -eq $jump ] && ! [ $i -eq $end ];then
printf "%d\n" "$i"
i=$new_start
jump=$end
fi
done
Tentu saja solusi ini lebih bertele-tele, beberapa hal bisa dipersingkat, tetapi berhasil. Diuji dengan ksh
, dash
, mksh
, dan tentu saja bash
.
Tetapi jika kita ingin membuat loop bash-spesifik (untuk alasan apa pun, mungkin tidak hanya mencetak tetapi juga melakukan sesuatu dengan angka-angka itu), kita juga dapat melakukan ini (pada dasarnya versi C-loop dari solusi portabel):
last=15; for (( i=1; i<=last;i++ )); do printf "%d\n" "$i"; [[ $i -eq $last ]] && ! [[ $i -eq 25 ]] && { i=19;last=25;} ;done
Atau dalam format yang lebih mudah dibaca:
last=15
for (( i=1; i<=last;i++ ));
do
printf "%d\n" "$i"
[[ $i -eq $last ]] && ! [[ $i -eq 25 ]] && { i=19;last=25;}
done
bash-4.3$ time bash -c 'printf "%d\n" {0..50000}>/dev/null'
real 0m0.196s
user 0m0.124s
sys 0m0.028s
bash-4.3$ time bash -c 'for i in {1..50000}; do echo $i > /dev/null; done'
real 0m1.819s
user 0m1.328s
sys 0m0.476s
bash-4.3$ time bash -c ' i=0;while [ $i -le 50000 ]; do echo $i>/dev/null; i=$((i+1)); done'
real 0m3.069s
user 0m2.544s
sys 0m0.500s
bash-4.3$ time bash -c 'for i in $(seq 1 50000); do printf "%d\n" > /dev/null; done'
real 0m1.879s
user 0m1.344s
sys 0m0.520s
Hanya karena kita dapat inilah solusi Python
$ python3 -c 'print("\n".join([str(i) for i in (*range(1,16),*range(20,26))]))'
Atau dengan sedikit cangkang:
bash-4.3$ python3 << EOF
> for i in (*range(16),*range(20,26)):
> print(i)
> EOF
touch $(printf "%d\n" {1..15} {20..25})
:-)
bash
Anda bahkan tidak perlu di $()
sana, hanya touch {1..15}.txt {20..25}.txt
:) Tapi tentu saja kita bisa menggunakan printf "%d\n
{1..15} {20..25} `dengan xargs
jika kita ingin melakukan lebih dari sekadar touch
file. Ada banyak cara untuk melakukan sesuatu dan itu membuat penulisan skrip jadi sangat menyenangkan!