Comment créer une séquence avec des zéros au début en utilisant le développement d'accolade

46

Lorsque j'utilise les éléments suivants, j'obtiens le résultat escompté:

$ echo {8..10}
8 9 10

Comment puis-je utiliser cette extension de manière très simple pour obtenir la sortie suivante?

$ echo {8..10}
08 09 10

J'ai maintenant que cela peut être obtenu en utilisant seq(n'a pas essayé), mais ce n'est pas ce que je cherche.

Des informations utiles peuvent être que je suis limité à cette version bash. (Si vous avez une zshsolution, mais pas de bashsolution, merci de la partager également)

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)
Bernhard
la source
Quelques astuces pour faire ceci dans bash 3 J'ai trouvé ici: mywiki.wooledge.org/BashFAQ/018 Cependant, l'approche décrite ici n'est pas pratique.
Bernhard

Réponses:

70

Préfixez le premier nombre avec un 0pour forcer chaque terme à avoir la même largeur.

$ echo {08..10}
08 09 10

De la section de la page de manuel bash sur Expansion de Brace:

Les nombres entiers fournis peuvent être précédés de 0 pour forcer chaque terme à avoir la même largeur. Lorsque x ou y commence par un zéro, le shell tente de forcer tous les termes générés à contenir le même nombre de chiffres, le remplissage à zéro le cas échéant.

Notez également que vous pouvez utiliser seql' -woption d'égaliser la largeur en ajoutant des zéros au début:

$ seq -w 8 10
08
09
10

$ seq -s " " -w 8 10
08 09 10

Si vous voulez plus de contrôle, vous pouvez même spécifier un format de style printf:

$ seq -s " " -f %02g 8 10
08 09 10
dogbane
la source
8
Après avoir découvert la echo {08..10}solution, elle n’a été introduite que pour la version 4 et les versions ultérieures de bash.
Bernhard
Cela me rend un peu mal à l'aise que bash fait cela. Pour un ensemble d'utilitaires (par exemple perl), un zéro à gauche indique un nombre octal. Je suppose que ce n'est pas souvent que vous voulez une séquence de nombres octaux ...
kurtm
5
Il est à noter que vous pouvez également préfixer les nombres lorsque vous passez à seqavec le -wcommutateur comme ceci: seq -w 003produit les nombres 001, 002 et 003.
slm
@kurtm ne vous inquiétez pas pour les zéros. Cela pourrait faire mal quand quelque chose essaie d'analyser un nombre. Cela est vraiment utile pour générer une séquence de noms de fichiers foo_00001.someextensionoù presque tous les contextes de tri fournissent un ordre sain.
Stéphane Gourichon
9

si vous utilisez printf

printf "%.2d " {8..10} 

cela forcera à avoir 2 caractères et ajoutera un 0 devant. Si vous avez besoin de 3 chiffres, vous pouvez changer en "% .3d".

BitsOfNix
la source
Merci pour votre réponse. Je suis conscient de la printfsolution, mais cela ne facilite pas vraiment les choses. J'espère qu'il y a une astuce cachée qui fait le travail :)
Bernhard
C'est la seule réponse qui semble suffisamment polyvalente pour gérer n'importe quelle circonstance, quelle que soit l'origine du numéro à composer. J'utilise un compteur lorsque je parcours des fichiers. Cette solution printf zéro pad parfaitement, tandis que tous les autres semblent se concentrer sur la génération de nombres remplis de zéros plutôt que sur les nombres existants.
mightypile
7

Utilisez une plage commençant par un chiffre constant et supprimez-la par une bande:

echo \ {108..110} | sed 's/ 1//g'

ou sans utiliser une commande externe:

a=({108..110}); echo "${a[@]#1}"

Pour une utilisation dans une boucle for:

for x in {108..110}; do
  x=${x#1}
  
done

cependant, dans ce cas, une boucle while serait plus claire et fonctionnera dans n’importe quel shell POSIX:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  
  x=$((x+1))
done
Gilles, arrête de faire le mal
la source
J'ai accepté cette réponse au-dessus des autres réponses, car elle répond à la demande de Bash 3.x. Surtout que j'avais forquand même besoin de la boucle.
Bernhard
6

J'ai la même version bash de l'affiche originale ( GNU bash, version 3.2.51(1)-release) et {08..12}ne fonctionne pas pour moi, mais ce qui suit fonctionne:

for i in 0{8..9} {10..12}; do echo $i; done
08
09
10
11
12

C'est un peu plus fastidieux, mais cela fonctionne sur la version OP de bash (et des versions ultérieures, je suppose).

Gregory Dulin
la source
Je ne pensais pas à cette solution (bien que dans mon cas, je souhaite aussi numéroter 0001 000, mais votre principe fonctionne bien entendu.
Bernhard
1

Pour référence, je pense que la largeur fixe automatique ne se produit qu'avec la dernière version de bash:

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

$ echo test{00..05}
test0 test1 test2 test3 test4 test5
Benjamin Goodacre
la source
-3
for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

les zéros, ini et fin sont des vars, il est donc facile d’écrire uniquement les zéros que vous dites en 'zéros' pour ini pour finir sans problèmes;)

miniminiyo
la source