Comment afficher les nombres en ordre inverse en utilisant seq (1)?


36

J'ai itérer sur les nombres dans divers ordre. Je peux les afficher par ordre croissant, même avec des étapes telles que:

$ seq --separator="," 1 10
1,2,3,4,5,6,7,8,9,10
$ seq --separator="," 1 2 10
1,3,5,7,9

Je suis également capable de les afficher dans l'ordre inverse, ni continu ni par étapes.

$ seq --separator="," 10 1   
$ seq --separator="," 10 2 1

Aucune sortie pour les commandes ci-dessus.

Les détails de ma coquille:

$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.

Dites-moi comment je pourrais afficher les nombres par ordre décroissant?


10
Pour les futurs lecteurs, seqc’est un outil totalement non standard et il n’ya aucune garantie que deux implémentations soient identiques. Si vous devez écrire une boucle qui parcourt les nombres en bash, utilisez-la for ((i=$max;i>=0;i--)) …ou similaire.
Kojiro

Réponses:


50

utiliser l'incrément négatif

seq -s, 10 -2 1
10,8,6,4,2

20

En général, vous ne voulez pas utiliser seq, ce n'est pas portable (même parmi les environnements Linux standard). Si vous utilisez ksh, zsh ou bash4 +, vous pouvez utiliser le développement d'accolade:

echo {10..1..2} | tr " " ,
10,8,6,4,2

1
C'est court et rapide, mais je suis sur une version plus ancienne de bash.
MTV

20
Bonne réponse, mais il y a une certaine ironie lorsque vous indiquez que ce seqn'est pas standard et que vous utilisez ensuite une extension bash-4-only. ;)
kojiro

@kojiro - Aucun argument pour être honnête ;-) Ma préoccupation principale n'est pas de savoir si la commande existe (cela peut ou non avoir de l'importance si le script est distribué / etc), mais si la commande s'exécute comme prévu par l'auteur. L’expansion de bash4 est presque garantie (si cela fonctionne, cela fonctionne comme vous le souhaitez), alors que ce seqn’est pas le cas.
Chris Down

1
Pourquoi n'est-il pas portable? Avez-vous des sources ou des preuves? Je suis intéressé.
Benoit Duffez

15

Une autre manière de pure bash, ksh ou zsh:

for ((i=10;i>0;i-=2)) ; do echo -n "$i," ; done

Un pur style POSIX:

i=10
while [ "$i" -gt 2 ]; do printf "$i,"; i=$((i-2)); done
echo "$i"

1
forLa deuxième expression devrait être le test et la troisième le pas.
manatwork

7

Maintenant, les standards POSIX:

awk 'BEGIN{for (i = 10; i > 0; i -= 2) print i}' | paste -sd , -

(intéressant, avec mawk(et dans une moindre mesure gawkaussi) beaucoup plus rapide que GNU seqpour i = 10000000au lieu de i = 10)

Ou

i=10; set --
while [ "$i" -gt 0 ]; do
  set -- "$@" "$i"
  i=$(($i - 2))
done
IFS=,
echo "$*"

(ne serait que plus efficace avec un petit nombre d'itérations, en particulier avec bash)

Ou

echo 'for(i=10;i>0;i-=2) i' | bc | paste -sd , -

(qui prend en charge des nombres de toute taille, mais notez qu’au-delà d’un certain nombre de chiffres (nombres supérieurs à 10 70 au moins dans les paramètres régionaux POSIX), les lignes sont entourées de barres obliques inverses)


1
Dans GNU bc, vous pouvez éviter le retour à la ligne en définissant BC_LINE_LENGTH=0l'environnement. Pas de chance sur d'autres implémentations.
Gilles 'SO- arrête d'être méchant'

1
Pourquoi utiliser les arguments de position plutôt que de faire une boucle s=$s,$iou d'appeler echo -n/ echo \c/ printf?
Gilles, arrête de faire le mal

2

Vous pouvez inverser l'ordre en utilisant tac(chat en sens inverse). Même si seqdevrait se comporter différemment sur différents systèmes, je pense que les éléments suivants devraient être aussi portables que possible:

$ seq 1 10 | tr '\012' ',' | sed 's/,$//'; echo
1,2,3,4,5,6,7,8,9,10
$ seq 1 10 | tac | tr '\012' ',' | sed 's/,$//'; echo
10,9,8,7,6,5,4,3,2,1
$

2

Essayez avec:

   seq [OPTION]... FIRST INCREMENT LAST

Exemple:

$ seq 10 -1 1

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.