Hepsi aynı genişliğe sahip olmak için bash'da bir tamsayı dizisini sıfırlamak nasıl?


426

Bazı değerleri döngü yapmam lazım,

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

İçin $firstve $lastben girişi ise sabit uzunlukta 5. Yani olması gerekiyor 1ben o olur ön öyle de sıfır eklemek gerekir, 00001. 99999Mesela ilmek yapılıyor , ama uzunluk 5 olmalı.

Örn: 00002, 00042, 00212, 012312ve hareketle bu yüzden.

Bunu nasıl yapabileceğime dair bir fikrin var mı?


22
İyi bir cevap şöyle olabilir: seq - w 1 99999. Seçenek -w çıkış uzunluğunu sabit tutar, 0 ile en kısa sayıları doldurur.
Bruno von Paris


Burada birçok cevap önerilir, for variable in $(something to generate the numbers); do ...ancak sayı listesi uzun olduğunda bu sorunludur. Kullanımı çok daha verimlidir something to generate the numbers | while read -r variable; do .... Ayrıca bkz. Mywiki.wooledge.org/DontReadLinesWithFor dosyalardan satır okuma vb. Tartışır , ancak bazı argümanlar burada da geçerlidir.
tripleee

Yanıtlar:


710

Özel durumunuzda , listenin çıktısını alırken sayıları biçimlendirmek için -fbayrağı kullanmak muhtemelen en kolay yöntemdir seq. Örneğin:

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

Aşağıdaki çıktıyı üretecektir:

00010
00011
00012
00013
00014
00015

Daha genel olarak, yerleşik olarak bashsahiptir printf, böylece çıktıları sıfırlarla aşağıdaki gibi doldurabilirsiniz:

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

-vÇıkışı başka bir değişkende depolamak için bayrağı kullanabilirsiniz :

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

Bildirim printfiçin biraz farklı bir biçimini destekleyen seqkullanmak gerekir böylece %05dyerine %05g.


5
%05g%05dbenim için düzeltmek yerine . "00026" bana "00022" veriyordu . Teşekkürler!
Ed Manet

12
Harika, kapsamlı bir cevap. Küçük bir düzeltme: açık konuşmak gerekirse, biçim karakterlerinin seqbir alt kümesini destekler . Bu printfdestekler (ve bu alt kümeleri içerir g, fakat d). Karakterlerin davranışı dve önceden düzeltilmiş sayılar dizelerini sekizlik sayılar olarak yorumlama ve ondalık sayıya dönüştürürken, ondalık sayıları olarak davranma biçiminde gfarklı davranır. (@EdManet: bu yüzden '00026' ile '00022'ye dönüştü ). Başka bir şey söz değer: does otomatik oluşturulan en geniş sayısına bağlı çıkış numaralarının sıfır dolgusu. d0gdseq -w
mklement0

Bu onaltılık karakterler listesi oluşturmama yardımcı oldu. for (( i = 0; i <= 0xffffffff; i++ )) do printf "%08x\n" $i ; done >> hex.txt8 karakterli bir onaltılık liste oluşturdu. Teşekkürler.
cde

seq --help: "FORMAT, 'double' türündeki bir bağımsız değişkeni yazdırmak için uygun olmalıdır; FIRST, INCREMENT ve LAST değerlerinin tümü maksimum hassas PREC ile sabit nokta ondalık sayılarıysa, varsayılan olarak% .PRECf, aksi takdirde% g olarak kullanılır." Mümkün olan dönüşüm belirteçleri olan efgaEFGA.
x-yuri

133

Daha kolay hala yapabilirsiniz

for i in {00001..99999}; do
  echo $i
done

16
Bu, Bash sürüm 4.1.2 (CentOS 6) üzerinde çalışır, ancak sürüm 3.2.25'te (CentOS 5) başarısız olur. Bunu yapmanın estetik açıdan daha hoş bir yol olduğunu kabul ediyorum!
Mike Starov

1
Çalışır, ancak
bashımda

Mac'te (Bash 4.4), bu rakamları doldurmaz. CentOS & SuSE'de harika çalışıyor!
Stefan Lasiewski

Bu Bash ile macOS üzerinde iyi çalışıyor4.4.23(1)-release
Whymarrh

Ne yazık ki Bash 5 üzerinde OS X üzerinde çalışmıyor, ne yazık ki
gotofritz

91

Sekansın sonunda maksimum dolgu uzunluğu varsa (örneğin, 5 basamak istiyorsanız ve komut "seq 1 10000" ise) seq için "-w" işaretini kullanabileceğinizden - dolgu ekler.

seq -w 1 10

üretmek

01
02
03
04
05
06
07
08
09
10

7
Bu kesinlikle doğru cevap. Neden bu kadar az oyu var? 😳
adius

5
kolay, çünkü dolgu ulaşmak istediğiniz maksimum sayıya bağlıdır. Bu daha önce hiç kaç sıfır ile bitireceğinizi bilmediğiniz bir parametredirse
guillem

5
Bu belirli bir sabit uzunluk vermez, sadece aynı uzunluktaki sonuçlar verir.
Ceisc

78

"% 05d" ile printf kullan, ör.

printf "%05d" 1

18

Kullanımı çok basit printf

[jaypal:~/Temp] printf "%05d\n" 1
00001
[jaypal:~/Temp] printf "%05d\n" 2
00002

12

Bunun gibi awk kullanın:

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

ÇIKTI:

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010

Güncelleme:

Saf bash alternatifi olarak, aynı çıktıyı elde etmek için bunu yapabilirsiniz:

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

Bu şekilde harici bir program kullanmaktan kaçınabilirsinizseq bir KULLANILAMAZ * nix tüm lezzetleri.


1
İfadeyi kullanmak awk's BEGINzorunda kalmamak için deyimi kullanabiliriz heredoc.
jaypal singh

@JaypalSingh: Teşekkürler dostum, bu iyi bir nokta. Cevabım güncellendi.
anubhava

9

Ben daha sonra sadece aradığım basamak sayısını kullanmak için kuyruk kullanın daha fazla basamak (sıfırlar) ile çıkış pad. Son beş haneyi almak için kuyrukta '6' kullanmanız gerektiğine dikkat edin :)

for i in $(seq 1 10)
do
RESULT=$(echo 00000$i | tail -c 6)
echo $RESULT
done

Kuyruğun -c argümanında doğru sayıda yer kullanmak istiyorsanız, 'echo -n 00000 $ i' kullanabilirsiniz, çünkü bu durur chars kuyruğundan biri olan bir satırsonu çıkarır, bu nedenle bu cevapta bir tane daha yüksek olun. Daha sonra ne yaptığınıza bağlı olarak, yeni satır bırakılırsa sonuçları etkileyebilir.
Ceisc

Döngüdeki değişkeni düzeltmek için harici bir işlem kullanmak oldukça verimsizdir. Bunun yerine kabuğun parametre genişletme özelliklerini kullanabilirsiniz . Bash'te belirli bir alt dizeyi indeksle çıkarmak için bir tesis vardır veya önek ve sonek ikamelerini, biraz ileri geri hareket etmesine rağmen, istenen genişliğe uyan bir desenle kullanabilirsiniz.
tripleee

4

N basamak istiyorsanız, 10 ^ N ekleyin ve ilk basamağı silin.

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

Çıktı:

01
02
03
04
05

2

Bu da işe yarayacaktır:

for i in {0..9}{0..9}{0..9}{0..9}
do
  echo "$i"
done

Güzel çözüm! Temiz, okunması kolay, ek program gerekmez.
Jonathan Cross

2

Diğer yol :

zeroos="000"
echo 

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

Herhangi bir sayı dönüştürmek için çok basit bir fonksiyon olurdu:

function leading_zero(){

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

}

1

Harici işlem çatalını kullanmadan bir yol, dize manipülasyonudur, genel bir durumda şöyle görünecektir:

#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

Çatallamanın gerçekten ağır bir işlem olduğu WSL'de de iyi çalışır. 110000 dosya listesi vardı, kullanarak printf "%06d" $NUM1 dakika sürdü, yukarıdaki çözüm yaklaşık 1 saniye içinde koştu.


0

1.) 1'den 1000'e kadar bir sayı dizisi oluşturun ve '-w' genişliğini sabitleyin (genişlik bitiş numarasının uzunluğuna göre belirlenir, bu durumda 1000 için 4 hane).

2.) Ayrıca, 'sed -n' kullanarak istediğiniz sayıları seçin (bu durumda 1-100 sayılarını seçeriz).

3.) her sayıyı 'yankı'. Sayılar, '$' kullanılarak erişilen 'i' değişkeninde saklanır.

Artıları: Bu kod oldukça temiz.

Eksileri: 'seq' tüm Linux sistemlerine özgü değil (anladığım kadarıyla)

for i in `seq -w 1 1000 | sed -n '1,100p'`; 
do 
    echo $i; 
done

0

Sabit uzunluğu elde etmek için sayıları sıfırlarla doldurduktan hemen sonra 10'a en yakın katı ekleyin. 2 basamak için, 10 ^ 2 ekleyin, ardından çıktıyı göstermeden önce ilk 1'i kaldırın.

Bu çözüm, herhangi bir uzunluktaki tek sayıları veya bir for döngüsü kullanarak bir tam sayı dizisini doldurmaya / biçimlendirmeye çalışır.

# 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

Mac OSX 10.6.8, Bash sürüm 3.2.48 üzerinde test edilmiştir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.