bash でゼロ埋めされた整数を反復処理するにはどうすればいいですか?

bash でゼロ埋めされた整数を反復処理するにはどうすればいいですか?

"[AZ][0-9]*" という形式、またはたとえば "A000001" という形式の文字列を反復処理するにはどうすればよいですか?

変数を受け取った後、分割します:

current_=$(mysql -h"$mysqlhost" -u"$mysqluser" -p"$PASS" "$DBNAME" -se "SELECT current_ FROM $GLOBALDB;")
current_number=$(echo $current_ | grep -oh "[0-9]*")
current_letter=$(echo $current_ | grep -oh "[A-Z]*")

しかし、1を追加しようとすると:

# add 1 & keep all leading zeros "000001"
next_number=$(printf %06d $(($current_number + 1)))

「000009」までカウントし、「000000」に戻ります。

そして私は次のように参加します:

next_=$(echo "$current_letter$next_number")

そして、Letter の反復処理に関しては、Associated Array を使用するか、または中括弧展開を使用することを考えていました{A..Z}が、これはまったく別の問題です。

答え1

ではbash、先頭にゼロがある数字は 8 進数として扱われます。強制的にbash10 進数として扱うには、プレフィックスを追加します10#

next_number=$(printf %06d "$((10#$current_number + 1))")

または、bash 3.1 以上では、フォークを回避するために次のようにします。

printf -v next_number %06d "$((10#$current_number + 1))"

(では10#-010として見られるように、これは負の数には機能しないので、 とは両方ともに展開されることに注意してください)。10#0 - 010bash$((10#-10))$((-10#-10))-8

参照:

$ printf 'A%06d\n' {5..12}
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012

または:

$ printf '%s\n' {A..C}{00008..00012}
A00008
A00009
A00010
A00011
A00012
B00008
B00009
B00010
B00011
B00012
C00008
C00009
C00010
C00011
C00012

または:

$ seq -f A%06g 5 12
A000005
A000006
A000007
A000008
A000009
A000010
A000011
A000012

答え2

Perl が救世主:

perl -E '$x = "A001"; say $x++ for 1 .. 1002' 

出力:

A001
A002
A003
A004
A005
A006
A007
A008
A009
A010
A011
...
A996
A997
A998
A999
B000
B001
B002

++ 演算子は文字と数字の両方を処理します。

答え3

歴史的な理由により、Bourne/POSIX スタイルのシェルでの数値演算では、先頭の0桁が 10 進数ではなく 8 進数である整数定数が解析されます。そのため、08算術演算では は構文エラーとなり、 の後続は078 となり、010は と同等になります8

通常の算術演算を使用してから、組み込み関数を使用して数値を印刷するときに数値を埋め込むことができますprintf

next_number=$(($current_number + 1))
printf -v padded_next_number %06d "$next_number"

-vのオプションはbashprintf特有のものです。POSIXの方法では

next_number=$(($current_number + 1))
padded_next_number=$(printf %06d "$next_number")

これは、コマンドがなかった従来のシステムで役立ちprintf、組み込みコマンドがないいくつかのシェルでもパフォーマンス向上に役立つもう1 つの方法ですprintf。1 から数えるのではなく、1000001 から数えます。こうすることで、数字の先頭にゼロを付ける必要がなくなります。数字を使用する場合は、先頭の数字を削除します1

number=1000000
while … ; do
  number=$((number+1))
  echo "${number#1}"
done

関連情報