2013-08-27 31 views
68

Ho un numero di base per il ciclo che incrementa la variabile num da 1 su ogni iterazione ...Come aggiungere gli zeri iniziali per il ciclo in shell?

for ((num=1; num<=5; num++)) 
do 
echo $num 
done 

quali uscite:

1 
2 
3 
4 
5 

Sto cercando di farlo produrre l'output (aggiungere uno zero prima di $ num):

01 
02 
03 
04 
05 

Senza fare:

echo 0$num 
+3

Usa 'printf' con un formato appropriato. – Barmar

+1

printf da bash ha molti effetti negativi, preferisco usare awk come segue: "num = $ (echo $ num | awk '{printf ("% 02d ", $ 1)}" " –

+0

@binogure Solo un avviso: Awk ha Comportamenti diversi su sistemi diversi Ci sono mawk, gawk, awk, nawk, ecc. Cerco di non raccomandarlo perché sembra che posso provarlo solo sul computer in cui lo sto scrivendo. Perl/Ruby sono più compatibili – piojo

risposta

5

perché non printf '%02d' $num? Vedere help printf per questo comando bash interno.

22

Usa printf comando per avere 0 padding:

printf "%02d\n" $num 

vostro ciclo for sarà simile a questo:

for ((num=1; num<=5; num++)); do printf "%02d\n" $num; done 
01 
02 
03 
04 
05 
+0

Non sono interessato a visualizzarlo sullo schermo (è per questo che viene utilizzato principalmente printf, giusto?) La variabile $ num verrà utilizzata come parametro per un altro programma, ma fammi vedere cosa posso fare con questo. –

+0

Spiegare chiaramente cosa si sta cercando di fare di quanto possa suggerire una risposta più adatta. – anubhava

+2

@BruceBlacklaws 'printf' nella shell viene utilizzato per creare stringhe da un elenco di argomenti. L'output sullo schermo è solo l'impostazione predefinita. In effetti, le shell pipeline sono l'ultimo esempio di programmazione funzionale: solo input, output, nessun effetto collaterale. ;-) –

32

seq -w rileverà larghezza e normalizzare esso.

for num in $(seq -w 01 05); do 
    ... 
done 

A quanto pare questo non funziona sulle versioni più recenti di iOS, in modo da poter installare MacPorts e utilizzare la sua versione di seq, oppure è possibile impostare il formato in modo esplicito:

seq -f '%02g' 1 3 
    01 
    02 
    03 

Ma data la bruttezza delle specifiche di formato per un problema così semplice, preferisco la soluzione che Henk e Adrian hanno dato, che usa solo Bash. Apple non può rovinare tutto poiché non c'è versione generica "unix" di Bash:

echo {01..05} 

Oppure:

for number in {01..05}; do ...; done 
+3

Just fyi 'seq' non è presente su OSX – anubhava

+1

È sulla mia macchina (OS X 10.7.5). La pagina man risale solo al 2010, quindi sembra essere un'aggiunta (relativamente) recente. – chepner

+1

non funziona su mac os sierra da 01 a 05, ma funziona da 01 a 10. – at0mzk

113

utilizzare la seguente sintassi:

$ for i in {01..05}; do echo "$i"; done 
01 
02 
03 
04 
05 

Se si desidera utilizzare printf, nulla impedisce di inserire il risultato in una variabile per ulteriore utilizzo:

$ foo=$(printf "%02d" 5) 
$ echo "${foo}" 
05 

Disclaimer: Funziona solo su >=bash-4.

+2

Risposta migliore, ed evita di usare comandi esterni goffi (come 'seq', non necessario in Bash corretto). Mi ha aiutato. –

+3

Sfortunatamente il {01..05} non funziona con le versioni precedenti di bash. Sono su un server con bash 3.2.51 e questo stamperà i numeri senza zeri iniziali. Sul mio desktop con 4.2.37 funziona bene però. – thomanski

+0

@thomanski Fair point, il [Changelog] (http://tiswww.case.edu/php/chet/bash/CHANGES) afferma che questa funzione è stata introdotta con 'bash-4.0-alpha': * L'espansione del brace ora consente di azzerare - il riempimento dei valori numerici espansi e aggiungerà il numero corretto di zeri per assicurarsi che tutti i valori contengano lo stesso numero di cifre.) *. –

4

Da bash 4.0 in poi, è possibile utilizzare Brace Expansion con stringhe di lunghezza fissa. Vedi sotto per l'annuncio originale.

Farà proprio quello che ti serve e non richiede nulla di esterno alla shell.

$ echo {01..05} 
01 02 03 04 05 

for num in {01..05} 
do 
    echo $num 
done 
01 
02 
03 
04 
05 

From the bash/NEWS file

Questa è una descrizione concisa delle nuove funzionalità aggiunte a bash-4.0 dal il rilascio di bash-3.2.

. . .

z. L'espansione Brace ora consente il riempimento a zero dei valori numerici espansi e aggiungerà il numero corretto di zeri per assicurarsi che tutti i valori contengano lo stesso numero di cifre.

+0

So che non ho specificato quale versione di BASH e quale piattaforma è in esecuzione ma questo flat fallisce su GNU bash, versione 3.2.57 (1) -release (x86_64-apple-darwin16) –

+0

@BruceBlacklaws Corretto. I numeri di lunghezza fissa sono stati aggiunti in 4.0. Inclusa la restrizione –

10

io non sono interessato a output allo schermo (che è quello che printf viene utilizzato principalmente per, giusto?) Il $ variabile num sta per essere utilizzato come parametro per un altro programma, ma lascia vedo cosa posso fare con questo.

È comunque possibile utilizzare printf:

for num in {1..5} 
do 
    value=$(printf "%02d" $num) 
    ... Use $value for your purposes 
done 
+2

Funziona ma la creazione di subshell è costosa. Per grandi sequenze potrebbe volerci molto tempo. –

1

Solo una nota: ho sperimentato comportamenti diversi su diverse versioni di bash:

  • versione 3.1.17 (1) -RELEASE - (x86_64-suse-linux) e
  • Versione 4.1.17 (9) -release (x86_64-unknown-cygwin))

per il precedente (3.1) for nn in (00..99) ; do ... funziona ma for nn in (000..999) ; do ... non funziona entrambi funzioneranno sulla versione 4.1; comportamento printf non hanno testato (bash --version ha dato le informazioni sulla versione)

Cheers, Jan

Problemi correlati