【问题标题】:Adding leading 0 in sed [duplicate]在 sed 中添加前导 0 [重复]
【发布时间】:2017-11-28 11:12:23
【问题描述】:

我想在一串数字中添加前导零,以便恰好有三个数字。例如考虑

echo "hello_1"   | sed -E 's/([0-9]+)/00\1/'  # hello_001
echo "hello_12"  | sed -E 's/([0-9]+)/0\1/'   # hello_012
echo "hello_123" | sed -E 's/([0-9]+)/\1/'    # hello_123

现在,问题是我在这里使用了三种不同的表达式,而我在一条线中被传送到sed。类似的东西

printf "hello_1\nhello_12\nhello_123\n" | sed -E 's/([0-9]+)/0\1/'
hello_01
hello_012
hello_0123

结果不是我要找的那个。预期的输出是

hello_001
hello_012
hello_123

我试过了

printf "hello_1\nhello_12\nhello_123\n" |  sed -r ":r;s/\b[0-9]{1,$((3-1))}\b/0&/g;tr"
hello_1
hello_12
hello_123

我从this post 得到的,但它不起作用,我不明白它是如何工作的。


我在 Linux 上使用 GNU sed version 4.2.1

【问题讨论】:

    标签: linux bash sed


    【解决方案1】:

    如果您可以考虑awk,那么使用printf 会容易得多:

    printf "hello_1\nhello_12\nhello_123\n" | awk -F_ '{printf "%s%s%03d\n", $1, FS, $2}'
    
    hello_001
    hello_012
    hello_123
    

    【讨论】:

    • awk 让 +1 变得简单!谢谢
    【解决方案2】:

    如果你想在左边用零填充到 3 位数字, 那么你可以使用两个正则表达式替换:

    • 用两个零填充替换 _[0-9]$
    • 用一个零填充替换_[0-9][0-9]$

    像这样:

    sed -E -e 's/_([0-9])$/_00\1/' -e 's/_([0-9][0-9])$/_0\1/'
    

    【讨论】:

      【解决方案3】:

      为什么它不起作用

      您尝试的sed 程序对您不起作用,因为它在左右两侧的单词边界 (\b) 上锚定数字,并且 _ 被视为单词字符(单词字符是字母、数字和下划线)。如果您将_ 替换为-(或空格),您会发现它有效:

      $ printf "hello-1\nhello-12\nhello-123\n" | sed -E ':a; s/\b[0-9]{1,2}\b/0&/g; ta'
      hello-001
      hello-012
      hello-123
      

      一般sed解决方案

      要针对一般情况(以及您的示例输入)修复它,您可以在左侧和右侧(结合使用^ 和 $ 处理行的开头和结尾):

      $ printf "hello_1\nhello_12\nhello_123\n" | sed -E ':a; s/(^|[^0-9])([0-9]{1,2})([^0-9]|$)/\10\2\3/g; ta'
      hello_001
      hello_012
      hello_123
      

      这与原始表达式的工作方式相似:它递归地将数字零添加到1-2 数字的任何孤立序列之前。只要进行了替换,分支命令t 就会循环到开头(标签:a)——即只要存在一个孤立的数字组,比3 字符短。

      捕获组\1 和\3 只是简单地传递\2 中捕获的数字周围的上下文。我们只需要它们来匹配一组孤立的数字。

      【讨论】:

        【解决方案4】:

        你也可以使用 perl:

        printf "hello_1\nhello_12\nhello_123\n" | perl -ne 's/(\d{1,3})$/sprintf("%3.3d", $1)/e; print;' -
        

        这会在输入行的末尾查找最多 3 位数字并将其更改为 3 位数字。

        【讨论】:

          【解决方案5】:

          此示例仅使用 sed,如果您想支持 3 个以上的零填充数字,它会很灵活。

          printf "hello_1\nhello_12\nhello_123\n" \
            | sed -e 's:_\([0-9]\):_00\1:;s:_0*\(...\):_\1:'
          

          如果您想要 8 个零填充数字仅使用 sed,则如下所示。

          printf "hello_1\nhello_12\nhello_123\n" \
            | sed -e 's:_\([0-9]\):_0000000000\1:;s:_0*\(........\):_\1:'
          

          如果不明显,发生的情况是 - 保留了原始数字部分,但在其前面插入了几个零。之后,第二个模式只保留最后 N 位,吞下多余的前导零。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-03-04
            • 1970-01-01
            • 1970-01-01
            • 2017-09-17
            • 2014-12-18
            • 1970-01-01
            相关资源
            最近更新 更多