如何将以零开头的数字视为十进制整数

如何将以零开头的数字视为十进制整数

输入将是如下文件名:

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

所有文件应该是连续的。我想找到丢失的连续文件名。为此,我使用分隔 6 位序列号awk 并使用grep使用正则表达式检查文件是否存在于目录中。

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

但 shell 脚本不会将数字视为十进制,并且如果我使用以下命令强制将数字视为十进制10#$序列号然后删除搜索文件所需的前面的零。

有没有办法解决?

答案1

某些 shell(例如 bash)在其算术表达式中将带有前导零的数字视为八进制。解决这个问题的一个技巧是仅操作带有额外非零前导数字的数字,例如从 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 shell,并避免为计算创建子进程,这可以使其更快(但无论如何,一百万次迭代可能会很慢,shell 的性能并不是最好的)。

在上面的脚本中,我没有使用涉及lswc来计算匹配文件的复杂而缓慢的命令,而是使用 shell 内置结构:set "A-B-$digits-."*将位置参数设置为匹配文件列表,下面的行打印匹配数 ( $#) if至少有一个匹配项(如果没有匹配项,则模式保持不变,因此[ -e "$1" ][ -e "A-B-$digits-.*" ]false)。

答案2

您可以使用该printf实用程序进行填充,例如,

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

两点:

  • 而 `foo` 和$(foo)都是标准,嵌套的 backtics 往往不那么便携
  • printf实用程序不仅仅用于填充。

答案3

wc -l如果文件名包含换行符,使用将不会产生正确的结果。

通过bashand zsh,您可以使用大括号扩展:

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

POSIXly:

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

相关内容