bash 正则表达式无法识别所有组

bash 正则表达式无法识别所有组

我需要从正则表达式中捕获组。但我似乎无法理解 bash 变量的概念BASH_REMATCH,因为我无法获得一些组。这是我的代码:

# I want to get the values around the first '=' if it exists
inp="short =  some word  long = span desc=sth to ' be ' described value=45"
regex="\s*(\w*)\s*=\s*(.*)"

if [[ $inp =~ $regex ]]; then 
  echo; 
  echo -e "input: \"$inp\""; 
  echo -e "regex: \"$regex\"";   
  echo "matching groups: ${#BASH_REMATCH[*]}"; 
  for i in $(seq 0 $(( ${#BASH_REMATCH[*]}-1 ))); do 
    echo -e "$i: \"${BASH_REMATCH[$i]}\""; 
  done; 
fi

input: "short =  some word  long = span desc=sth to ' be ' described value=45"
regex: "\s*(\w*)\s*=\s*(.*)"
matching groups: 3
0: "=  some word  long = span desc=sth to ' be ' described value=45"
1: ""
2: "  some word  long = span desc=sth to ' be ' described value=45"

我预计第一组会“矮”。为什么不被认可呢?如果我在 regex101.com 上测试我的正则表达式,它会告诉我第 1 组“short”。链接如下: https://regex101.com/r/oZGQS6/1


编辑1

第一组使用 sed 进行识别(我使用了相同的正则表达式,只是转义了分组括号):

$ sed 's/\s*\(\w*\)\s*=\s*\(.*\)/\1\n\2/' <<< $inp
short
some word  long = span desc=sth to ' be ' described value=45

编辑2

正如所建议的,我尝试将锚点放入正则表达式,但这次没有识别到​​结果:

regex="^\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)$"
regex="^\s*(\w+)\s*=\s*(.*)$"

这些正则表达式都不起作用,我根本没有结果。

我检查了字符串的十六进制值:

$ od -vAn -tx1c <<<"$inp"
           73  68  6f  72  74  20  3d  20  20  73  6f  6d  65  20  77  6f
           s   h   o   r   t       =           s   o   m   e       w   o
           72  64  20  20  6c  6f  6e  67  20  3d  20  73  70  61  6e  20
           r   d           l   o   n   g       =       s   p   a   n    
           64  65  73  63  3d  73  74  68  20  74  6f  20  27  20  62  65
           d   e   s   c   =   s   t   h       t   o       '       b   e
           20  27  20  64  65  73  63  72  69  62  65  64  20  76  61  6c
               '       d   e   s   c   r   i   b   e   d       v   a   l
           75  65  3d  34  35  0a                                        
           u   e   =   4   5  \n 

看起来并不是什么奇怪的角色。

有关信息,我在 mac 上使用 bash v 4.4.0:

$ bash --version
GNU bash, version 4.4.0(1)-release (x86_64-apple-darwin15.6.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

编辑3

一些新的。我在 Linux 机器上尝试过,使用的是 bash v.4.1.2,效果较差:

$ bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

所有这三个正则表达式都有效:

regex="\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)"
regex="^\s*(\w*)\s*=\s*(.*)$"
regex="^\s*(\w+)\s*=\s*(.*)$"

我得到结果:

input: "short =  some word  long = span desc=sth to ' be ' described value=45"
regex: "^\s*(\w*)\s*=\s*(.*)"
matching groups: 3
0: "short =  some word  long = span desc=sth to ' be ' described value=45"
1: "short"
2: "some word  long = span desc=sth to ' be ' described value=45"

这正是我所期望的结果。但为什么它在我的 Mac 上无法正常工作? Bash 版本更新。我想要一个适用于所有最新版本的 bash 的解决方案。

答案1

Bash 的正则表达式没有锚定。这意味着它们可以匹配字符串中的任何位置。这取决于您的正则表达式引擎。此处,匹配从等号开始,如 所示BASH_REMATCH[0]

^解决办法:在字符串的开头添加a regex

[更新] 如上所述,bash使用您的正则表达式引擎 ( man 3 regex),该引擎可能因平台而异。如果您的正则表达式有问题,请避免使用\letter快捷方式并使用 Posix 等效项。

例如,而不是regex="^\s*(\w*)\s*=\s*(.*)"
使用regex="^[[:space:]]*([_[:alnum:]]*)[[:space:]]*=[[:space:]]*(.*)"

相关内容