So erstellen Sie eine Sequenz mit führenden Nullen mithilfe der geschweiften Klammer

45

Wenn ich Folgendes verwende, erhalte ich wie erwartet ein Ergebnis:

$ echo {8..10}
8 9 10

Wie kann ich diese Klammererweiterung auf einfache Weise verwenden, um die folgende Ausgabe zu erhalten?

$ echo {8..10}
08 09 10

Ich weiß jetzt, dass dies mit seq(nicht ausprobiert) erreicht werden kann, aber das ist nicht das, wonach ich suche.

Nützliche Informationen können sein, dass ich auf diese Bash-Version beschränkt bin. (Wenn Sie eine zshLösung, aber keine bashLösung haben, teilen Sie diese bitte mit.)

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)
Bernhard
quelle
Einige Hinweise, um dies in Bash 3 zu tun, habe ich hier gefunden: mywiki.wooledge.org/BashFAQ/018 Der dort beschriebene Ansatz ist jedoch nicht praktisch.
Bernhard

Antworten:

70

Stellen Sie der ersten Zahl ein voran, um 0zu erzwingen, dass jeder Term dieselbe Breite hat.

$ echo {08..10}
08 09 10

Im Abschnitt der Bash-Manpage zur Klammererweiterung:

Versorgte Ganzzahlen können mit dem Präfix 0 versehen werden, um zu erzwingen, dass jeder Term dieselbe Breite hat. Wenn entweder x oder y mit einer Null beginnen, versucht die Shell, alle generierten Terme zu zwingen, die gleiche Anzahl von Ziffern zu enthalten.

Beachten Sie auch, dass Sie seqdie -wOption zum Ausgleich der Breite verwenden können, indem Sie mit führenden Nullen auffüllen:

$ seq -w 8 10
08
09
10

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

Wenn Sie mehr Kontrolle wünschen, können Sie sogar ein printf-Format angeben:

$ seq -s " " -f %02g 8 10
08 09 10
Dogbane
quelle
8
Nachdem Sie sich gerade über die echo {08..10}Lösung informiert haben, wird sie nur für die Bash-Version 4 und höher eingeführt.
Bernhard
Das macht es mir ein bisschen unangenehm, dass Bash das macht. Für eine Reihe von Dienstprogrammen (zum Beispiel perl) gibt eine führende Null eine Oktalzahl an. Ich nehme an, Sie möchten nicht oft eine Folge von Oktalzahlen ...
kurtm
5
Es ist zu beachten, dass Sie die Zahlen auch voranstellen können, wenn Sie dann seqmit dem -wSchalter wie seq -w 003
folgt vorgeben
@kurtm mach dir keine Sorgen um führende Nullen. Das könnte weh tun, wenn etwas versucht, eine Zahl zu analysieren. Dies ist wirklich nützlich, um eine Dateinamenfolge zu generieren, foo_00001.someextensionbei der fast alle Sortierkontexte eine sinnvolle Reihenfolge liefern.
Stéphane Gourichon
9

wenn Sie printf verwenden

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

Dies erzwingt 2 Zeichen und fügt eine führende 0 hinzu. Wenn Sie 3 Stellen benötigen, können Sie zu "% .3d" wechseln.

BitsOfNix
quelle
Danke für deine Antwort. Ich kenne die printfLösung, aber sie macht es nicht wirklich einfacher. Ich hoffe, dass es einen versteckten Trick gibt, der den Job macht :)
Bernhard
Dies ist die einzige Antwort, die vielseitig genug zu sein scheint, um alle Umstände für die Herkunft der aufzuschreibenden Nummer zu berücksichtigen. Ich verwende einen Zähler, während ich Dateien durchlaufe. Diese printf-Lösung füllt fehlerfrei mit Nullen auf, während sich alle anderen scheinbar darauf konzentrieren, mit Nullen aufgefüllte Zahlen zu generieren, anstatt vorhandene Zahlen mit Nullen aufzufüllen.
Mightypile
7

Verwenden Sie einen Bereich, der mit einer konstanten Ziffer beginnt, und entfernen Sie diese Ziffer:

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

oder ohne Verwendung eines externen Befehls:

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

Zur Verwendung in einer for-Schleife:

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

In diesem Fall wäre eine while-Schleife klarer und funktioniert in jeder POSIX-Shell:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  
  x=$((x+1))
done
Gilles 'SO - hör auf böse zu sein'
quelle
Ich habe diese Antwort vor den anderen Antworten akzeptiert, da sie die Anforderung für Bash 3.x erfüllt. Zumal ich die forSchleife sowieso brauchte .
Bernhard
6

Ich habe die gleiche Bash-Version des ursprünglichen Posters ( GNU bash, version 3.2.51(1)-release) und {08..12}funktioniert bei mir nicht, aber Folgendes funktioniert:

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

Es ist etwas langweiliger, aber es funktioniert auf der OP-Version von Bash (und späteren Versionen, würde ich annehmen).

Gregory Dulin
quelle
Ich habe nicht über diese Lösung
Bernhard
1

Als Referenz denke ich, dass die automatische feste Breite nur mit der neuesten Version von Bash auftritt:

$ 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
quelle
-3
for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

Nullen, Ini und Fin sind Vars, also ist es einfach, nur Nullen zu schreiben, die man in 'Nullen' sagt, damit Ini ohne Probleme zu Finnen wird;)

miniminiyo
quelle