J'essaie de parcourir deux séquences dans la même boucle dans mon shell comme ci-dessous:
#!/bin/bash
for i in (1..15) and (20..25) ;
do
echo $i
......
.....other process
done
une idée comment je peux y arriver?
J'essaie de parcourir deux séquences dans la même boucle dans mon shell comme ci-dessous:
#!/bin/bash
for i in (1..15) and (20..25) ;
do
echo $i
......
.....other process
done
une idée comment je peux y arriver?
Réponses:
Vous avez seulement besoin d'une extension de soutien pour cela
$ for n in {1..3} {200..203}; do echo $n; done
1
2
3
200
201
202
203
Nous pouvons passer une liste à for( ).for i in x y z; do stuff "$i"; done
Donc, ici, les accolades { }obtiennent le shell pour développer vos séquences dans une liste. Vous avez seulement besoin de mettre un espace entre eux, car le shell divise les listes d'arguments sur ceux-ci.
echoles chiffres
touchfichiers, ils peuvent le faire touch {1..15}.txt {20..25}.txt, aucune boucle n'est nécessaire ici. Mais bien sûr, si c'est plusieurs actions sur le même numéro - OK, cela pourrait utiliser une boucle.
Alternativement, nous pouvons utiliser seq( imprimer une séquence de nombres ), voici deux exemples équivalents:
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
S'il s'agit d'un script, pour des tâches répétitives, vous pouvez utiliser des fonctions:
#!/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"
La réponse de Zanna et la réponse de pa4080 sont à la fois bien et je serais probablement aller avec l' un d'eux dans la plupart des cas. Cela va peut-être de soi, mais pour être complet, je le dirai quand même: vous pouvez charger chaque valeur dans un tableau puis boucler sur le tableau. Par exemple:
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
La réponse de Zanna est absolument correcte et bien adaptée à bash, mais nous pouvons encore améliorer cela sans utiliser de boucle.
printf "%d\n" {1..15} {20..25}
Le comportement de printfest tel que si le nombre de ARGUMENTSest supérieur aux contrôles de format 'FORMAT STRING', alors tout printfsera divisé ARGUMENTS en morceaux égaux et continuera de les ajuster à la chaîne de formatage jusqu'à ce qu'il soit épuisé ARGUMENTS.
Si nous recherchons la portabilité, nous pouvons utiliser à la printf "%d\n" $(seq 1 15) $(seq 20 25)place
Allons plus loin et plus amusant. Disons que nous voulons effectuer une action plutôt que d'imprimer simplement des nombres. Pour créer des fichiers à partir de cette séquence de nombres, nous pourrions facilement le faire touch {1..15}.txt {20..25}.txt. Et si nous voulons que plusieurs choses se produisent? Nous pourrions également faire quelque chose comme ceci:
$ printf "%d\n" {1..15} {20..25} | xargs -I % bash -c 'touch "$1.txt"; stat "$1.txt"' sh %
Ou si nous voulons le faire à l'ancienne:
printf "%d\n" {1..15} {20..25} | while read -r line; do
touch "$line".txt;
stat "$line".txt;
rm "$line".txt;
done
Si nous voulons créer une solution de script qui fonctionne avec des shells qui n'ont pas d'expansion d'accolade (ce {1..15} {20..25}sur quoi repose), nous pouvons écrire une simple boucle while:
#!/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
Bien sûr, cette solution est plus verbeuse, certaines choses pourraient être raccourcies, mais cela fonctionne. Testé avec ksh, dash, mkshet, bien sûr bash.
Mais si nous voulions créer une boucle spécifique à bash (pour une raison quelconque, peut-être pas seulement en imprimant mais aussi en faisant quelque chose avec ces nombres), nous pouvons également le faire (essentiellement une version en boucle C de la solution portable):
last=15; for (( i=1; i<=last;i++ )); do printf "%d\n" "$i"; [[ $i -eq $last ]] && ! [[ $i -eq 25 ]] && { i=19;last=25;} ;done
Ou dans un format plus lisible:
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
Tout simplement parce que nous pouvons voici la solution Python
$ python3 -c 'print("\n".join([str(i) for i in (*range(1,16),*range(20,26))]))'
Ou avec un peu de coquille:
bash-4.3$ python3 << EOF
> for i in (*range(16),*range(20,26)):
> print(i)
> EOF
touch $(printf "%d\n" {1..15} {20..25}):-)
bashvous n'en avez même pas besoin $(), juste touch {1..15}.txt {20..25}.txt :) Mais bien sûr, nous pourrions utiliser printf "%d\n{1..15} {20..25} `avec xargssi nous voulions faire plus que de simples touchfichiers. Il y a plusieurs façons de faire les choses et cela rend le script tellement amusant!