Jak zerować Pad sekwencji liczb całkowitych w bash tak, że wszystkie mają tę samą szerokość?

Muszę zapętlić kilka wartości,

for i in $(seq $first $last)
do
    does something here
done

Dla $first i $last, musi mieć stałą długość 5. Więc jeśli wejście jest 1, muszę dodać zera z przodu tak, że staje się 00001. Pętli do 99999 na przykład, ale długość musi być 5.

E. g.: 00002, 00042, 00212, 012312 i tak dalej.

Jak mogę to zrobić?

13 answers

W twoim konkretnym przypadku, chociaż prawdopodobnie najłatwiej jest użyć flagi -f do seq, aby sformatować liczby podczas wyświetlania listy. Na przykład:

for i in $(seq -f "%05g" 10 15)
do
  echo $i
done

Wygeneruje następujące wyjście:

00010
00011
00012
00013
00014
00015

Bardziej ogólnie, bash ma printf jako wbudowany, więc można pad wyjście z zerami w następujący sposób:

$ i=99
$ printf "%05d\n" $i
00099

Możesz użyć znacznika -v do przechowywania danych wyjściowych w innej zmiennej:

$ i=99
$ printf -v j "%05d" $i
$ echo $j
00099

Zauważ, że printf obsługuje nieco inny format niż seq więc musisz użyć %05d zamiast %05g.

 793
Author: Dave Webb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-09 14:26:12

Easier still you can just do

for i in {00001..99999}; do
  echo $i
done
 145
Author: Indie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-20 09:43:26

Jeśli koniec sekwencji ma maksymalną długość wypełnienia (na przykład, jeśli chcesz 5 cyfr i komend jest "seq 1 10000"), to możesz użyć flagi "- w"dla seq-dodaje ono samo wypełnienie.

seq -w 1 10

Produce

01
02
03
04
05
06
07
08
09
10
 104
Author: m_messiah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-17 11:07:57

Użyj printf z "%05D " np.

printf "%05d" 1
 85
Author: frankc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-09 14:15:22

Bardzo proste użycie printf

[jaypal:~/Temp] printf "%05d\n" 1
00001
[jaypal:~/Temp] printf "%05d\n" 2
00002
 23
Author: jaypal singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-09 14:15:29

Użyj awk Tak:

awk -v start=1 -v end=10 'BEGIN{for (i=start; i<=end; i++) printf("%05d\n", i)}'

Wyjście:

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010

Update:

Jako alternatywa Pure bash możesz to zrobić, aby uzyskać to samo wyjście:

for i in {1..10}
do
   printf "%05d\n" $i
done

W ten sposób możesz uniknąć używając zewnętrznego programu seq, który jest niedostępny na wszystkich smakach *nix.

 12
Author: anubhava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-09 14:38:11

I pad wyjście z większą liczbą cyfr (zer) niż potrzebuję następnie użyć tail, aby użyć tylko liczby cyfr Szukam. Zauważ, że musisz użyć '6' w ogonie, aby uzyskać ostatnie pięć cyfr:)

for i in $(seq 1 10)
do
RESULT=$(echo 00000$i | tail -c 6)
echo $RESULT
done
 9
Author: unifex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 01:45:05

Jeśli chcesz N cyfr, dodaj 10^N i usuń pierwszą cyfrę.

for (( num=100; num<=105; num++ ))
do
  echo ${num:1:3}
done

Wyjście:

01
02
03
04
05
 4
Author: Burghard Hoffmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-26 12:21:40

W inny sposób:

zeroos="000"
echo 

for num in {99..105};do
 echo ${zeroos:${#num}:${#zeroos}}${num}
done

Tak prostą funkcją do konwersji dowolnej liczby byłoby:

function leading_zero(){

    local num=$1
    local zeroos=00000
    echo ${zeroos:${#num}:${#zeroos}}${num} 

}
 4
Author: Paco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-17 10:57:19

Jednym ze sposobów bez użycia zewnętrznego rozwidlenia procesu jest manipulacja łańcuchami, w ogólnym przypadku wyglądałoby to tak:

#start value
CNT=1

for [whatever iterative loop, seq, cat, find...];do
   # number of 0s is at least the amount of decimals needed, simple concatenation
   TEMP="000000$CNT"
   # for example 6 digits zero padded, get the last 6 character of the string
   echo ${TEMP:(-6)}
   # increment, if the for loop doesn't provide the number directly
   TEMP=$(( TEMP + 1 ))
done

Działa to całkiem dobrze również na WSL, gdzie forking jest naprawdę ciężką operacją. Miałem listę plików 110000, użycie printf "%06d" $NUM zajęło ponad 1 minutę, powyższe rozwiązanie działało w około 1 sekundy.

 4
Author: Tamisoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-04 21:03:05

To również zadziała:

for i in {0..9}{0..9}{0..9}{0..9}
do
  echo "$i"
done
 2
Author: Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 03:19:37

1.) Tworzy sekwencję liczb " seq "od 1 do 1000 i ustala szerokość "- w " (szerokość jest określona przez długość liczby końcowej, w tym przypadku 4 cyfry dla 1000).

2.) Wybieramy również, które liczby chcemy wybrać za pomocą 'sed-n' (w tym przypadku wybieramy liczby 1-100).

3.) "echo" z każdej liczby. Liczby są przechowywane w zmiennej "i", do której dostęp uzyskuje się za pomocą"$".

Plusy: ten kod jest całkiem czysty.

Wady: 'seq' nie jest natywny dla wszystkich systemów Linux (jak I zrozumieć)

for i in `seq -w 1 1000 | sed -n '1,100p'`; 
do 
    echo $i; 
done
 0
Author: nick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-07 18:04:32

Jeśli po wypełnieniu cyfr zerami osiągniesz stałą długość, po prostu dodaj najbliższą wielokrotność 10 np. dla 2 cyfr dodaj 10^2, a następnie usuń pierwsze 1 przed wyświetlaniem wyjścia.

To rozwiązanie działa do Pad / formatowania pojedynczych liczb o dowolnej długości lub całego ciągu liczb za pomocą pętli for.

# Padding 0s zeros:
# Pure bash without externals eg. awk, sed, seq, head, tail etc.
# works with echo, no need for printf

pad=100000      ;# 5 digit fixed

for i in {0..99999}; do ((j=pad+i))
    echo ${j#?}
done

Testowane na Mac OSX 10.6.8, Bash ver 3.2.48

 0
Author: Zimba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-27 17:29:24