0で始まる数値を10進整数として扱う方法

0で始まる数値を10進整数として扱う方法

入力は次のファイル名になります。

A-B-000001-C
A-B-000002-C
.....
.....
A-B-999999-C

すべてのファイルは連続している必要があります。不足している連続ファイル名を見つけたいです。これには別の6桁のシリアル番号を使用します。アッ そして使用grep正規表現を使用して、ディレクトリにファイルがあることを確認します。

`ls|grep "A-B-${sequencenumber}-.*"|wc -l`

ただし、シェルスクリプトは数値を10進数として扱わず、次のように数字を10進数として扱うように強制する10#$シリアル番号その後、ファイルを検索するために必要な先頭のゼロを削除します。

この問題を解決する方法はありますか?

答え1

一部のシェル(例:bash)は、算術式の前にゼロの数字を8進数として扱います。この問題を解決する 1 つの方法は、1000001 から 1999999 までの計算など、前にゼロ以外の数字が追加された数字に対してのみ操作を実行することです。前にゼロのある希望の数値を取得するには、文字列操作を使用して前の1を削除します。

n=1000001
while [ "$n" -le 1999999 ]; do
  digits=${n#1}
  set "A-B-$digits-."*
  if [ -e "$1" ] || [ -L "$1" ]; then
    echo "${digits}: $#"
  fi
  n=$((n+1))
done

この方法はすべてのPOSIXシェルに移植可能であり、計算用のサブプロセスを生成しないため、高速化することができます(ただし、100万回の繰り返しはとにかく遅く、シェルのパフォーマンスは最高ではありません)。

上記のスクリプトでは、一致するファイルを含めてls計算するwc複雑で遅いコマンドを使用する代わりに、シェル組み込み構成を使用します。set "A-B-$digits-."*位置引数を一致するファイルのリストに設定すると、次の行は一致する数($#)を印刷します。一致する項目が1つ以上あります(一致する項目がない場合、パターンは変更されずに保持されるため[ -e "$1" ]false [ -e "A-B-$digits-.*" ])。

答え2

printfたとえば、このユーティリティを使用して以下を入力できます。

$(ls|grep "A-B-$(printf '%06d' $sequencenumber)-.*"|wc -l)

2つの点:

  • そして`foo`と$(foo)両方です基準、ネストされたバックティックは移植性が低下する傾向があります。
  • これprintfユーティリティはパディングだけのためのものではありません。

答え3

wc -lファイル名に改行文字が含まれている場合、使用すると正しい結果は生成されません。

bashzsh支柱の拡張を使用できます。

for n in {000001..999999}; do
  f=A-B-$n-C
  [ -f "$f" ] || printf '%s missing\n' "$f"
done

ksh93オプションで有効braceexpand

for n in {1..999999%06d}; do
  : the code above
done

kshと では、zsh次のことができます。

typeset -Z6 i=1
max=999999
while [ "$i" -le "$max" ]; do
  f=A-B-$i-C
  [ -f "$f" ] || printf '%s missing\n' "$f"
  : "$((i+=1))"
done

POSIX的に:

min=1
max=999999
while [ "$min" -le "$max" ]; do
  f=$(printf "A-B-%0${#max}d-C" "$min")
  [ -f "$f" ] || printf '%s missing\n' "$f"
  : "$((min+=1))"
done

答え4

awk私のために働く:

set x=`echo $< | awk '{printf "%d",$1}' ` ; echo $x
033      # this is what I entered
33       # this prints out

関連情報