すべてが同じ幅になるようにbashで整数のシーケンスをゼロ埋めする方法は?


428

いくつかの値をループする必要があります。

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

ため$first$last、iが入力されるのであれば、それは固定長5であることが必要1、私はそれはとなるフロントようにゼロを追加する必要があります0000199999たとえば、ループしますが、長さは5でなければなりません。

例えば:000020004200212012312と述べそう。

どうすればそれを行うことができるのですか?


22
良い答えは次のようになります。配列- 0で最短の番号をパディング、出力な長さを一定に保つ-w 99999 1ワットオプション
ブルーノ・フォン・パリ


ここでは多くの回答が推奨されてfor variable in $(something to generate the numbers); do ...いますが、これは数値のリストが長い場合に問題になります。使用する方がはるかに効率的something to generate the numbers | while read -r variable; do ...です。ファイルからの行の読み取りなどについて説明しているmywiki.wooledge.org/DontReadLinesWithForも参照してください。ただし、ここでもいくつかの引数が適用されます。
tripleee 2018年

回答:


711

特定のケースでは、リストを出力するときに-fフラグを使用しseqて数値をフォーマットするのがおそらく最も簡単です。例えば:

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

次の出力が生成されます。

00010
00011
00012
00013
00014
00015

より一般的にbashprintf、が組み込みであるため、次のように出力にゼロを埋め込むことができます。

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

-vフラグを使用して、出力を別の変数に格納できます。

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

printfは少し異なる形式をサポートしているseqので、%05dではなくを使用する必要があることに注意してください%05g


5
%05g%05d私のためにそれを修正する代わりに。 「00026」「00022」をくれました。ありがとう!
Ed Manet

12
すばらしい包括的な答え。1つの小さな修正:厳密に言えば、フォーマット文字のサブセットseqサポートします。それはサポートします(そしてそのサブセットにはは含まれますが、含まれません)文字の行動とその中に微妙に異なって解釈して数字の文字列を-prefixed のに対し、数字と小数点に変換小数として扱い、それら。(@EdManet:これが、「00026」がで「00022」に変わった理由です)。もう一つの価値が言及:ない自動生成された最も広い数に基づいて、出力数のゼロパディングを。printfgddgd0gdseq -w
mklement0 2013

これは、16進文字リストを生成するのに役立ちました。for (( i = 0; i <= 0xffffffff; i++ )) do printf "%08x\n" $i ; done >> hex.txt8文字の16進数リストを作成しました。ありがとう。
cde 2014年

seq --help:「FORMATは、タイプ 'double'の1つの引数を出力するのに適している必要があります。FIRST、INCREMENT、LASTがすべて最大精度PRECの固定小数点10進数である場合、デフォルトで%.PRECfになり、それ以外の場合は%gになります。 " 可能な変換指定子efgaEFGAです。
x-yuri

133

さらに簡単にできる

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

16
これはBashバージョン4.1.2(CentOS 6)では機能しますが、バージョン3.2.25(CentOS 5)では失敗します。これは、これを行うためのより審美的に楽しい方法であることに同意します!
マイクStarov

1
機能しますが、私のbashでゼロが埋め込まれた文字列は提供されません
user2707001 '19 / 10/19

Mac(Bash 4.4)では、これは数字を埋めません。CentOSとSuSEでは、うまく機能します!
Stefan Lasiewski、

これは、Bashを使用するmacOSで正常に機能します4.4.23(1)-release
Whymarrh

悲しいことに、OS XのBash 5では動作しません
gotofritz '

91

シーケンスの終わりにパディングの最大長がある場合(たとえば、5桁が必要で、コマンドが "seq 1 10000"の場合)、seqに "-w"フラグを使用できます。パディング自体が追加されます。

seq -w 1 10

作物

01
02
03
04
05
06
07
08
09
10

7
これは明らかに正しい答えです。なぜ賛成票が非常に少ないのですか?ad
adius

5
パディングは到達したい最大数に依存するため、簡単です。これがパラメーターである場合、最終的に何個のゼロになるかは事前にわかりません
guillem

5
これは、指定された固定長ではなく、すべて同じ長さの結果を提供します。
Ceisc 2017



12

次のようにawkを使用します。

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

出力:

00001
00002
00003
00004
00005
00006
00007
00008
00009
00010

更新:

純粋なbashの代替として、これを実行して同じ出力を取得できます。

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

この方法は、あなたがすることができないよう、外部プログラム使用してseqいる利用できないでの* nixのすべての味にします。


1
awk's BEGINステートメントを使用して、heredoc割り当てを使用する必要がないようにすることができます。
jaypal sing 2012

@JaypalSingh:ありがとうメイト、それは良い点だ。私の答えを更新しました。
anubhava 2012年

9

出力に必要な桁数(ゼロ)を埋め込んでから、tailを使用して、探している桁数のみを使用します。最後の5桁を取得するには、末尾に「6」を使用する必要があることに注意してください。

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

tailの-c引数で正しい数の場所を使用したい場合は、 'echo -n 00000 $ i'を使用できます。これにより、tailが返す文字の1つである改行の出力が停止するため、次のようにする必要があります。この回答では1つ高くなります。何をしているのかに応じて、改行が残っていると、結果に影響を与える可能性があります。
Ceisc 2017

外部プロセスを使用してループ内の変数をトリムすることは、かなり非効率的です。代わりに、シェルのパラメーター拡張機能を使用できます。Bashには、特定の部分文字列をインデックスで抽出する機能があります。または、前後に少し必要なものの、希望の幅に一致するパターンで接頭辞と接尾辞の置換を使用できます。
tripleee 2018年

4

N桁が必要な場合は、10 ^ Nを追加して最初の桁を削除します。

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

出力:

01
02
03
04
05

2

これも機能します:

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

素敵な解決策!クリーンで読みやすく、追加のプログラムは必要ありません。
ジョナサンクロス

2

他の方法 :

zeroos="000"
echo 

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

したがって、任意の数値を変換する単純な関数は次のようになります。

function leading_zero(){

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

}

1

外部プロセスフォークを使用しない1つの方法は、文字列操作です。一般的なケースでは、次のようになります。

#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

これは、フォークが非常に重い操作であるWSLでも非常にうまく機能します。私は110000ファイルのリストを持っていて、printf "%06d" $NUM1分以上かかって、上のソリューションは約1秒で実行されました。


0

1.)1から1000までの数字のシーケンス 'seq'を作成し、幅 '-w'を固定します(幅は終了番号の長さによって決まります。この場合、1000の場合は4桁です)。

2.)また、「sed -n」を使用して、必要な数を選択します(この場合、1〜100の数を選択します)。

3.)各番号を「エコー」します。数値は変数「i」に格納され、「$」を使用してアクセスされます。

長所:このコードはかなりクリーンです。

短所: 'seq'はすべてのLinuxシステムにネイティブではありません(私が理解しているように)

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

0

数値をゼロで埋めて固定長を達成した直後の場合は、最も近い10の倍数を追加します。2桁の場合、10 ^ 2を追加し、出力を表示する前に最初の1を削除します。

このソリューションは、任意の長さの単一の数値、または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

Mac OSX 10.6.8、Bash ver 3.2.48でテスト済み

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.