Come creare una sequenza con zeri iniziali utilizzando l'espansione del controvento


46

Quando utilizzo quanto segue, ottengo un risultato come previsto:

$ echo {8..10}
8 9 10

Come posso utilizzare questa espansione parentesi graffa in modo semplice, per ottenere il seguente output?

$ echo {8..10}
08 09 10

Ora che questo può essere ottenuto usando seq(non ho provato), ma non è quello che sto cercando.

Informazioni utili potrebbero essere che sono limitato a questa versione bash. (Se hai una zshsoluzione, ma nessuna bashsoluzione, condividi anche tu )

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)

Qualche suggerimento per farlo in bash 3 ho trovato qui: mywiki.wooledge.org/BashFAQ/018 Tuttavia, l'approccio delineato non è conveniente.
Bernhard

Risposte:


70

Prefisso il primo numero con a 0per forzare ogni termine ad avere la stessa larghezza.

$ echo {08..10}
08 09 10

Dalla sezione della pagina man bash su Brace Expansion:

Gli interi forniti possono essere preceduti da 0 per forzare ogni termine ad avere la stessa larghezza. Quando x o y inizia con uno zero, la shell tenta di forzare tutti i termini generati a contenere lo stesso numero di cifre, con spaziatura zero ove necessario.

Si noti inoltre che è possibile utilizzare seqcon l' -wopzione per equalizzare la larghezza riempiendo con zeri iniziali:

$ seq -w 8 10
08
09
10

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

Se vuoi un maggiore controllo, puoi persino specificare un formato di stile printf:

$ seq -s " " -f %02g 8 10
08 09 10

8
Dopo aver appena scoperto la echo {08..10}soluzione, tuttavia, è stata introdotta solo per bash versione 4 e successive.
Bernhard

Questo mi mette un po 'a disagio che bash lo faccia. Per un gruppo di utilità (ad esempio perl) uno zero iniziale indica un numero ottale. Suppongo che spesso non desideri una sequenza di numeri ottali ...
Kurtm,

5
Va notato che puoi anche aggiungere il prefisso ai numeri quando lo dai quindi seqcon l' -winterruttore in questo modo: seq -w 003produce i numeri 001, 002 e 003.
slm

@kurtm non preoccuparti di portare a zero. Ciò potrebbe ferire quando qualcosa tenta di analizzare un numero. Ciò a cui è veramente utile è generare una sequenza di nomi di file in foo_00001.someextensioncui quasi tutti i contesti di ordinamento forniscono un ordinamento sano.
Stéphane Gourichon,

9

se usi printf

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

questo costringerà a essere 2 caratteri e aggiungerà uno 0. Se hai bisogno di 3 cifre puoi cambiare in "% .3d".


Grazie per la tua risposta. Sono a conoscenza della printfsoluzione, ma non sta davvero rendendo tutto più semplice. Spero che ci sia qualche trucco nascosto che fa il lavoro :)
Bernhard

Questa è l'unica risposta che sembra abbastanza versatile da gestire qualsiasi circostanza per l'origine del numero da pad. Sto usando un contatore mentre cerco i file. Questa soluzione printf zero pad senza problemi mentre tutti gli altri sembrano concentrarsi sulla generazione di numeri zero-padding piuttosto che zero-padding numeri esistenti.
poderoso

7

Usa un intervallo che inizia con una cifra costante e rimuovi quella cifra:

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

o senza usare un comando esterno:

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

Per l'uso in un ciclo for:

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

anche se in questo caso un ciclo while sarebbe più chiaro e funziona in qualsiasi shell POSIX:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  
  x=$((x+1))
done

Ho accettato questa risposta sopra le altre risposte, perché soddisfa la richiesta di Bash 3.x. Soprattutto perché avevo bisogno del forciclo comunque.
Bernhard,

6

Ho la stessa versione bash del poster originale ( GNU bash, version 3.2.51(1)-release) e {08..12}non funziona per me, ma quanto segue:

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

È un po 'più noioso, ma funziona sulla versione OP di bash (e versioni successive, suppongo).


Non ho pensato a questa soluzione (anche se nel mio caso in realtà voglio anche contare il numero 0001 1000, ma il tuo principio funziona ovviamente.
Bernhard

1

Per riferimento, penso che la larghezza fissa automatica si verifichi solo con l'ultima versione di 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

-3
for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

zeri, ini e pinna sono vari, quindi è facile, scrivi solo zeri che dici in 'zeri' per ini a pinna senza problemi;)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.