Jak utworzyć sekwencję z wiodącymi zerami za pomocą interpretacji nawiasów


45

Kiedy używam następujących, otrzymuję wynik zgodnie z oczekiwaniami:

$ echo {8..10}
8 9 10

Jak w łatwy sposób użyć tego rozszerzenia nawiasu klamrowego, aby uzyskać następujące wyniki?

$ echo {8..10}
08 09 10

Teraz mogę to uzyskać za pomocą seq(nie próbowałem), ale nie tego szukam.

Przydatne informacje mogą być takie, że jestem ograniczony do tej wersji bash. (Jeśli masz zshrozwiązanie, ale nie ma bashrozwiązania, udostępnij również)

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

Podpowiedź do zrobienia tego w bash 3 znalazłem tutaj: mywiki.wooledge.org/BashFAQ/018 Jednak przedstawione tam podejście nie jest wygodne.
Bernhard

Odpowiedzi:


70

Poprzedź pierwszą cyfrę a, 0aby wymusić, aby każdy termin miał tę samą szerokość.

$ echo {08..10}
08 09 10

Z sekcji strony podręcznika bash w Brace Expansion:

Dostarczone liczby całkowite mogą być poprzedzone 0, aby wymusić, aby każdy element miał taką samą szerokość. Kiedy x lub y zaczyna się od zera, powłoka próbuje wymusić, aby wszystkie wygenerowane warunki zawierały tę samą liczbę cyfr, w razie potrzeby uzupełniając zero.

Należy również pamiętać, że można korzystać seqz -wopcji, aby wyrównać szerokość przez napawanie z wiodącymi zerami:

$ seq -w 8 10
08
09
10

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

Jeśli chcesz mieć większą kontrolę, możesz nawet określić format stylu printf:

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

8
Po tym, jak właśnie dowiedziałem się o echo {08..10}rozwiązaniu, jest on wprowadzany tylko dla wersji bash 4 i nowszych.
Bernhard

To sprawia, że ​​czuję się trochę nieswojo, gdy robi to bash. W przypadku wielu narzędzi (na przykład perl) wiodące zero wskazuje liczbę ósemkową.
Podejrzewam,

5
Należy zauważyć, że można również poprzedzać liczby przy sequżyciu -wprzełącznika w następujący sposób: seq -w 003produkuje liczby 001, 002 i 003.
slm

@kurtm nie martw się o wiodące zera. To może boleć, gdy coś próbuje parsować liczbę. Przydaje się to generowanie sekwencji nazw plików, w foo_00001.someextensionktórej prawie wszystkie konteksty sortowania zapewniają rozsądne porządkowanie.
Stéphane Gourichon

9

jeśli używasz printf

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

wymusi to 2 znaki i doda wiodące 0. W przypadku, gdy potrzebujesz 3 cyfr, możesz zmienić na „% .3d”.


Dzięki za odpowiedź. Jestem świadomy printfrozwiązania, ale tak naprawdę nie ułatwia tego. Mam nadzieję, że jest jakaś ukryta sztuczka, która spełnia swoje zadanie :)
Bernhard

Jest to jedyna odpowiedź, która wydaje się na tyle uniwersalna, aby poradzić sobie z każdą okolicznością dotyczącą pochodzenia liczby do uzupełnienia. Korzystam z licznika, gdy przeglądam pliki. To rozwiązanie printf zeruje pady bezbłędnie, podczas gdy wszystkie inne wydają się skupiać na generowaniu liczb wypełnionych zerami, a nie na istniejących liczbach.
mightypile

7

Użyj zakresu zaczynającego się od stałej cyfry i usuń tę cyfrę:

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

lub bez użycia zewnętrznego polecenia:

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

Do użytku w pętli for:

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

choć w tym przypadku pętla while byłaby wyraźniejsza i działałaby w dowolnej powłoce POSIX:

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

Przyjąłem tę odpowiedź ponad inne, ponieważ spełnia ona wymagania dotyczące Bash 3.x. Zwłaszcza, że ​​i tak potrzebowałem forpętli.
Bernhard

6

Mam tę samą wersję bash oryginalnego posteru ( GNU bash, version 3.2.51(1)-release) i {08..12}nie działa dla mnie, ale następujące działania:

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

Jest to trochę bardziej nużące, ale działa na OP wersji bash (i późniejszych wersji, jak przypuszczam).


Nie zastanawiałem się nad tym rozwiązaniem (chociaż w moim przypadku faktycznie chcę również numer 0001 1000, ale twoja zasada działa oczywiście.
Bernhard

1

Dla porównania, myślę, że automatyczna stała szerokość występuje tylko w najnowszej wersji 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

zera, ini i płetwa są zmiennymi, więc łatwo jest pisać tylko zera, które wypowiadasz w „zerach”, aby ini bez problemu działały;)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.