Cara membuat urutan dengan nol terkemuka menggunakan ekspansi brace

46

Ketika saya menggunakan yang berikut ini, saya mendapatkan hasil seperti yang diharapkan:

$ echo {8..10}
8 9 10

Bagaimana saya bisa menggunakan ekspansi brace ini dengan cara yang mudah, untuk mendapatkan output berikut?

$ echo {8..10}
08 09 10

Saya sekarang bahwa ini dapat diperoleh menggunakan seq(tidak mencoba), tetapi bukan itu yang saya cari.

Info yang berguna mungkin saya terbatas pada versi bash ini. (Jika Anda memiliki zshsolusi, tetapi tidak ada bashsolusi, silakan berbagi juga)

$ bash -version
GNU bash, version 3.2.51(1)-release (x86_64-suse-linux-gnu)
Bernhard
sumber
Beberapa petunjuk untuk melakukan ini di bash 3 saya temukan di sini: mywiki.wooledge.org/BashFAQ/018 Namun, pendekatan yang diuraikan di sana tidak nyaman.
Bernhard
stackoverflow.com/questions/8789729/zero-padding-in-bash
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

70

Awali angka pertama dengan a 0untuk memaksa setiap istilah memiliki lebar yang sama.

$ echo {08..10}
08 09 10

Dari bagian bash man page di Brace Expansion:

Bilangan bulat yang disediakan dapat diawali dengan 0 untuk memaksa setiap istilah memiliki lebar yang sama. Ketika x atau y dimulai dengan nol, shell mencoba untuk memaksa semua istilah yang dihasilkan mengandung jumlah digit yang sama, zero-padding jika diperlukan.

Juga catatan bahwa Anda dapat menggunakan seqdengan -wpilihan untuk menyamakan lebar oleh bantalan dengan nol terkemuka:

$ seq -w 8 10
08
09
10

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

Jika Anda ingin lebih banyak kontrol, Anda bahkan dapat menentukan format gaya printf:

$ seq -s " " -f %02g 8 10
08 09 10
dogbane
sumber
8
Namun, setelah baru mengetahui echo {08..10}solusinya, itu hanya diperkenalkan untuk bash versi 4 dan lebih tinggi.
Bernhard
Itu membuat saya sedikit tidak nyaman bahwa bash melakukan itu. Untuk sekelompok utilitas (misalnya perl) nol di depan menunjukkan angka oktal. Saya kira tidak sering Anda menginginkan urutan angka oktal ...
kurtm
5
Perlu dicatat bahwa Anda juga dapat mengawali angka-angka ketika memberi kemudian ke seqdengan -wsaklar seperti: seq -w 003menghasilkan angka 001, 002, dan 003.
slm
@kurtm jangan khawatir tentang memimpin nol. Itu bisa menyakitkan ketika sesuatu mencoba mengurai angka. Apa ini benar-benar berguna adalah untuk menghasilkan urutan nama file di foo_00001.someextensionmana hampir semua konteks penyortiran menyediakan urutan yang waras.
Stéphane Gourichon
9

jika Anda menggunakan printf

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

ini akan memaksa menjadi 2 karakter dan akan menambah angka 0. Jika Anda membutuhkan 3 digit Anda dapat mengubah ke "% .3d".

BitsOfNix
sumber
Terima kasih atas jawaban anda. Saya menyadari printfsolusinya, tetapi tidak benar-benar membuat ini lebih mudah. Saya berharap ada beberapa trik tersembunyi yang berhasil :)
Bernhard
Ini adalah satu-satunya jawaban yang tampaknya cukup fleksibel untuk menangani keadaan apa pun asal mula nomor tersebut. Saya menggunakan penghitung saat saya mengulang file. Solusi printf ini nol bantalan tanpa cacat sementara semua yang lain tampaknya fokus pada menghasilkan angka-angka nol-bantalan daripada angka-angka nol-padding yang ada.
mayypile
7

Gunakan rentang yang dimulai dengan angka konstan dan hapus angka itu:

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

atau tanpa menggunakan perintah eksternal:

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

Untuk digunakan dalam for for:

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

meskipun untuk kasus ini loop sementara akan lebih jelas dan bekerja di shell POSIX:

x=8
while [ $x -le 10 ]; do
  n=$((100+x)); n=${n#1}
  
  x=$((x+1))
done
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Saya menerima jawaban ini di atas jawaban lain, karena memenuhi permintaan untuk Bash 3.x. Terutama karena saya memerlukan forloop.
Bernhard
6

Saya memiliki versi bash yang sama dari poster asli ( GNU bash, version 3.2.51(1)-release) dan {08..12}tidak berfungsi untuk saya, tetapi yang berikut tidak:

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

Ini sedikit lebih membosankan, tetapi ia bekerja pada versi OP bash (dan versi yang lebih baru, saya akan berasumsi).

Gregory Dulin
sumber
Saya tidak memikirkan solusi ini (walaupun dalam kasus saya, saya sebenarnya juga ingin nomor 0001 1000, tetapi prinsip Anda berfungsi tentu saja.
Bernhard
1

Sebagai referensi, saya pikir lebar tetap otomatis hanya terjadi pada versi terbaru dari 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
Benjamin Goodacre
sumber
-3
for i in $(seq -s " " -f %0${zeros}g $ini $fin); do ....;done

nol, ini dan sirip adalah vars, jadi itu mudah, kamu hanya menulis nol yang kamu katakan dalam 'nol' untuk ini sampai sirip tanpa masalah;)

miniminiyo
sumber