【问题标题】:CLI: Increment a number in a string while keeping padded zeroesCLI:在字符串中增加一个数字,同时保持填充零
【发布时间】:2019-11-16 17:22:57
【问题描述】:

我目前使用这个 perl 命令来增加字符串中的最后一个数字:

perl -pe 's/(\d+)(?!.*\d+)/$1+1/e' <<< "abc123_00456.txt"

它输出abc123_457.txt,而我想要abc123_00457.txt

我还希望将99 之类的内容增加到100,但如果这太难了,00 也是可以接受的。

我想要的更多示例:

09 -> 10
004 -> 005

我还希望能够增加任意数字(不仅仅是 1),所以没有++

我不想使用 shell 的内置函数来完成这个。

【问题讨论】:

  • 提示:(?!.*\d+) 可以简化为(?!.*\d),最好使用/s,因为没有理由检查换行符。

标签: regex string perl sed command-line


【解决方案1】:

这可能对你有用(GNU sed 和 Bash):

sed -E 's/^([^0-9]*([0-9]+[^0-9]+)*0*)([0-9]+)(.*)/echo "\1$((\3+1))\4"/e' file

【讨论】:

    【解决方案2】:

    使用 GNU awk 将第三个参数匹配():

    $ awk -v n=17 'match($0,/(.*[^0-9])([0-9]+)(.*)/,a){$0=a[1] sprintf("%0*d",length(a[2]),a[2]+n) a[3]} 1' <<< "abc123_00456.txt"
    abc123_00473.txt
    

    在每个 UNIX 机器上的任何 shell 中使用任何 awk:

    $ awk -v n=17 'match($0,/[0-9]+\./){lgth=RLENGTH-1; tgt=substr($0,RSTART,lgth); $0=substr($0,1,RSTART-1) sprintf("%0*d",lgth,tgt+n) substr($0,RSTART+lgth)} 1' <<< "abc123_00456.txt"
    abc123_00473.txt
    

    【讨论】:

    • 如果数字在字符串的开头则不起作用,例如00456.txt.
    • 是的,但数字不在字符串的开头(如果可以的话,这是一个简单的调整)。如果数字是指数或浮点格式,它也不起作用,但这也不是 OP 向我们展示的示例输入。
    【解决方案3】:

    您可以使用带有sprintf的格式化字符串:

    perl -pe 's/(\d+)(?!.*\d)/sprintf("%05d",$1+1)/e' <<< "abc123_00456.txt"
    

    5 表示数字的宽度,0 是用于填充数字的字符。

    对于未知宽度,您可以动态构建格式化字符串:

    perl -pe 's/(\d+)(?!.*\d)/sprintf("%0".length($1)."d",$1+1)/e' <<< "abc123_00456.txt"
    

    【讨论】:

    • 零的个数并不特定于 5。
    • @HappyFace: 5 是整数的宽度,而不是零的个数。
    • 数字的宽度不是常数。
    • @HappyFace:好的,你总是加 1 吗?
    • 不,那也不是常数,我是通过“${1:-1}”设置的。
    【解决方案4】:

    试试这个:

    perl -pe 's/(\d+)(?=\D*\z)/my $n = $1; ++$n/e' <<< "abc123_00456.txt"
    

    递增字符串时的++ 运算符preserves the number of digits

    或者:

    perl -pe 's/(\d+)(?=\D*\z)/sprintf "%0*d", length($1), $1 + 1/e' <<< "abc123_00456.txt"
    

    这使您可以增加不止 1(或执行其他算术运算)。

    sprintf %d 以十进制格式格式化整数。 0 表示用零填充结果; * 表示最大字段宽度取自下一个参数,而不是格式字符串本身。 (例如,%05d 的意思是“通过用零填充数字来格式化数字,直到它至少有 5 个字符宽”。)

    这里我们只取原始数字字符串 (length($1)) 的长度并将其用作我们的字段宽度。要格式化的数字是$1 + 1。如果它比原始字符串短,sprintf 会自动添加零。

    另见perldoc -f sprintf

    【讨论】:

    • 这行得通,但我希望能够概括增加的数字(不仅仅是 1)。
    猜你喜欢
    • 2014-12-30
    • 2010-09-24
    • 2011-03-08
    • 2015-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2012-02-17
    相关资源
    最近更新 更多