ubuntuusers.de

bash Variablengenerierung mit führenden Nullen

Status: Gelöst | Ubuntu-Version: Kein Ubuntu
Antworten |

Antiqua Team-Icon

Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

Mahlzeit,

Ich hätte gerne folgendes "Problem" in der Bash:

Ich gebrauche gerne for-Schleifen mit Zählung z.B. von 1 - 25 und benutze dann die Zahl auch zur Generierung von Dateinamen oder Ähnlichem. Allerdings habe ich gerne führende Nullen. Ich behelfe mir momentan mit so einem Konstrukt:

for i in {1..25}; do j="00$i"; k=${j:(-2)}; echo "$k-File_irgendwas.txt"; done

das generiert jetzt so eine führende Null bei den einstelligen Zahlen. Wie es so für mehr führende Nullen geht (z.B. dreistellig), weiß ich. Das ist also nicht mein Problem.

Nun die Frage: Das geht doch sicher irgendwie noch einfacher?

Bin für jeden Vorschlag dankbar...

LG:
Antiqua

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

k="$(printf '%03d' "$i")"

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

Und es steht geschrieben in der heiligen Schrift:

       A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or  single
       characters,  and  incr,  an  optional  increment, is an integer.  When integers are supplied, the
       expression expands to each number between x and y, inclusive.  Supplied integers may be  prefixed
       with  0  to  force  each term to have the same width.  When either x or y begins with a zero, the
       shell attempts to force all generated terms to contain the same number  of  digits,  zero-padding
       where  necessary.

Sodann:

$ for i in {01..25}; do echo "$i-File_irgendwas.txt"; done 

Antiqua Team-Icon

(Themenstarter)
Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

diesch schrieb:

k="$(printf '%03d' "$i")"

danke, interessant und funktioniert bei bash 3 und bash 4:)

Vain schrieb:

$ for i in {01..25}; do echo "$i-File_irgendwas.txt"; done 

hmmm.... geht bei einer bash 4, aber nicht bei einer bash 3, da kommt sowas:

(GNU bash, version 3.1.17)
$ for i in {01..11}; do echo "$i-File_irgendwas.txt"; done
1-File_irgendwas.txt
2-File_irgendwas.txt
3-File_irgendwas.txt
4-File_irgendwas.txt
5-File_irgendwas.txt
6-File_irgendwas.txt
7-File_irgendwas.txt
8-File_irgendwas.txt
9-File_irgendwas.txt
10-File_irgendwas.txt
11-File_irgendwas.txt

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2503

Antiqua schrieb:

geht bei einer bash 4, aber nicht bei einer bash 3

Jo, das geht erst ab Version 4. Die Bash 4 ist aber bald zwei Jahre alt und du hattest es auf keine bestimmte Version eingeschränkt, ergo… 😉

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

Antiqua schrieb:

diesch schrieb:

k="$(printf '%03d' "$i")"

danke, interessant und funktioniert bei bash 3 und bash 4:)

Das funktioniert auch mit sh und jeder anderen POSIX-kompatiblen Shell

Antiqua Team-Icon

(Themenstarter)
Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

Vain schrieb:

Jo, das geht erst ab Version 4. Die Bash 4 ist aber bald zwei Jahre alt und du hattest es auf keine bestimmte Version eingeschränkt, ergo…

stimmt, ich hatte keine Version angegeben. Aber zu meiner Verteidigung, es gibt doch noch einige, die bash v.3 verwenden, RHEL-5.5, CentOs 5.5, SLES 11, Debian Lenny, Slackware 13.0, Ubuntu Hardy, ... 😉

diesch schrieb:

Das funktioniert auch mit sh und jeder anderen POSIX-kompatiblen Shell

gut zu wissen, so gehts also sogar mit der dash. Danke nochmal.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17596

Wohnort: Berlin

Die for-Schleife kann man sich noch sparen:

echo {09..12}"-File_irgendwas.txt"

aber ich sage nicht, bei welcher Version. ☺ Hardy ist ja 8.04, und out-of-service, oder? Ach nein, 3 Jahre, erst in 3 Monaten, also.

Antiqua Team-Icon

(Themenstarter)
Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

user unknown schrieb:

Die for-Schleife kann man sich noch sparen: >

echo {09..12}"-File_irgendwas.txt"

so schon, aber das oben war nur Beispielcode.

Im echten Script passiert in der Schleife einiges, wo ich die Variable pro Durchlauf jeweils mit der passenden fortlaufenden Nummer brauche und nicht pro Durchlauf 4 x Aufsteigend Dateinamen 09-blablub bis 12-blablubb (um bei deinem Beispiel zu bleiben)

aber ich sage nicht, bei welcher Version. ☺ Hardy ist ja 8.04, und out-of-service, oder? Ach nein, 3 Jahre, erst in 3 Monaten, also.

Hardy Desktop hat noch bis April 2011, stimmt.

Aber ich kenn jemand, der hat nen Freund, dessen Schwester mit nem Typen geht, dessen Großvater kennt jemanden noch vom Krieg her und der Enkel von dem wiederum behauptet, es gibt noch ein paar Rechner, wo irgensowas komisches läuft. "Sörvah" nennt der das... ka was das ist, Tante Guhgl kann mir da auch nicht weiterhelfen. Naja, jedenfalls schwafelt der immer irgendwas von "Unterstützt bis April 2013" ... *AufDieUhrGuck* ... da is ja dann doch noch was hin 😎

Und die anderen genannten sind zwar jetzt explicit keine Ubuntus, aber z.T. noch länger unterstützt.

LG:
Antiqua

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17596

Wohnort: Berlin

Antiqua schrieb:

user unknown schrieb:

Die for-Schleife kann man sich noch sparen: >

echo {09..12}"-File_irgendwas.txt"

so schon, aber das oben war nur Beispielcode.

Im echten Script passiert in der Schleife einiges, wo ich die Variable pro Durchlauf jeweils mit der passenden fortlaufenden Nummer brauche und nicht pro Durchlauf 4 x Aufsteigend Dateinamen 09-blablub bis 12-blablubb (um bei deinem Beispiel zu bleiben)

Tja - das war dem Beispielcode nicht zu entnehmen, so ohne Kristallkugel, und wenn Du den Namen mehrfach brauchst, dann nützt es wohl nichts, aber ohne besseren Beispielcode kann man nicht wissen, ob nicht auf die for-Schleife verzichtet werden könnte.

gekmihesg

Anmeldungsdatum:
6. Mai 2009

Beiträge: 106

Wie wäre es hiermit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
pad() {
        local s=$1 c=${2:-0} p=${3:- }
        while [ ${#s} -lt $c ] ; do s="${p:0:$c - ${#s}}$s" ; done
        echo "$s"
}

pad 1 3
# -> "  1"

pad 123 5 0
# -> "00123"

pad xyz 5 abc
# -> "abxyz"

Antiqua Team-Icon

(Themenstarter)
Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

user unknown schrieb:

Tja - das war dem Beispielcode nicht zu entnehmen, so ohne Kristallkugel, und wenn Du den Namen mehrfach brauchst, dann nützt es wohl nichts, aber ohne besseren Beispielcode kann man nicht wissen, ob nicht auf die for-Schleife verzichtet werden könnte.

Ich hab den Beispielcode bewusst einfach gewählt. Mir gings wirklich nur um die Vereinfachung von j="00$i"; k=${j:(-2)};, (das dann für die bash v3 benötigt wird, weil das Script auf ner alten Kiste rennen soll) nicht um die ganze Schleife.

Wobei es scheint, als wäre meine Version eh schon die mit den wenigsten Tastenanschlägen bei kurzen Variablen 😉

j="0$i"; k=${j:(-2)}        
k="$(printf '%02d' "$i")"

gekmihesg schrieb:

Wie wäre es hiermit:

nette Funktion, aber ich wollte es einfacher, nicht noch komplexer. Hab mir das Schnipsel aber mal vorsichtshalber archiviert 😀

track

Avatar von track

Anmeldungsdatum:
26. Juni 2008

Beiträge: 7174

Wohnort: Wolfen (S-A)

Die ganze Umspeicherei brauchst Du aber nicht wirklich.
Ein simples

[ $i -le 9 ] && i=0$i

tut es auch. Nicht kürzer als Dein Code, aber übersichtlicher.

Übrigens ist hier gar kein Quoting nötig: ($i ist ja nie leer und enthält auch keine Leerzeichen)

i=$(printf %02d $i)

LG,

track

theinlein

Anmeldungsdatum:
29. Dezember 2007

Beiträge: 1279

unabhängig von der bash Version kann man auch auf 'seq' zurückgreifen, um alle möglichen Numerierungen zu erzeugen

man seq

Antiqua Team-Icon

(Themenstarter)
Avatar von Antiqua

Anmeldungsdatum:
30. Dezember 2008

Beiträge: 4534

@track

[ $i -le 9 ] && i=0$i funktioniert gut, wenn ich nur bei den einstelligen Zahlen eine Null brauch, wenn ich bei den einstelligen 2 Nullen und bei den zweistelligen eine Null will, brauchts dann eben zwei tests.

Auf das mit den Anführungszeichen bin ich auch schon gekommen, aber das ich ja die gleiche Variable nehmen kann, hab ich übersehen. Danke für den Hinweis.

@ theinlein

an seq hab ich auch schon gedacht, aber das bring ich nur dazu auf die gleiche Länge mit vorangestellten Nullen aufzufüllen. Kein Problem bei 1..15, da bekomm ich schön 01, 02, etc. aber wenn ich z.B. nur 1..9 hab (was auch vorkommen kann) macht seq -w keine führenden Nullen. Mit dem -f Flag war ich überfordert. Aber das bräuchte es wohl irgendwie, wenn ich z.B. auf 001..015 auffüllen will. Deshalb hab ich das sein lassen.

LG:
Antiqua

Antworten |