使用 sed 正则表达式仅捕获数字部分

使用 sed 正则表达式仅捕获数字部分

为什么以下不起作用?

INTERNAL_NUM=$(grep -E '\s*internal_num\s*=' file.xml |sed -E 's/internal_num\s*=\s*([0-9]\+)/\1/') 
echo "$INTERNAL_NUM"

我想打印出实际的数字,但它打印:

internal_num = 1234 

grep命令打印出来internal_num = 1234,所以该部分没问题。这是sed不起作用的管道。

答案1

如果你有 GNU grep,你可以写

grep -oP '\binternal_num\s*=\s*\K\d+' file.xml

但您不应该使用正则表达式来解析 XML。也许你需要这样的东西

$ echo '
      <root>
          <tag>
              <tag>
                  <wanted internal_num="1234" />
                  <wanted internal_num = "5678" />
              </tag>
          </tag>
      </root>
  ' | xmlstarlet sel -t -v '//@internal_num' -n
1234
5678

请显示您的输入文件。

答案2

不同的工具和给定工具的实现/版本支持不同的正则表达式语法。

为了便于移植,您可以限制自己使用 POSIX 功能集:

s=[[:space:]]
sed -n "s/^\(.*$s\)\{0,1\}internal_num$s*=$s*\([0-9]\{1,\}\).*/\2/p"

(假设每行只出现一次)

如果您知道您只会在grep支持GNU-o和(对于类似 perl 的正则表达式)的系统上运行它,您可以这样做:-Pgrep

grep -Po '(?<!\S)internal_num\s*=\s*\K\d+'

答案3

您正在使用扩展正则表达式,但仍然转义\+,因此它会查找文字加号并且不会调用替换。

尝试,

INTERNAL_NUM=$(grep -E '\s*internal_num\s*=' file.xml |sed -E 's/internal_num\s*=\s*([0-9]+)/\1/') 
echo "$INTERNAL_NUM"

测试用例(在 GNU sed V4.2.1 上测试):

$ echo "internal_num = 1234" | sed -E 's/internal_num\s*=\s*([0-9]\+)/\1/'
internal_num = 1234

$ echo "internal_num = 1234" | sed -E 's/internal_num\s*=\s*([0-9]+)/\1/'
1234

正如其他答案提到的(并详细解释),您应该认真考虑不使用正则表达式来解析 XML。

相关内容