Bash正则表达式匹配“ 0xffffffc0006e0584在some_function中(/path/to/my/file.c:93)。”

时间:2019-09-04 23:04:21

标签: regex bash

在我正在编写的Bash脚本中,我需要捕获这一行中的navigationItem/path/to/my/file.c

93

在regex101.com的帮助下,我设法创建了此Perl正则表达式:

0xffffffc0006e0584 is in some_function (/path/to/my/file.c:93).
0xffffffc0006e0584 is in another_function(char *arg1, int arg2)  (/path/to/my/other_file.c:94).

但是我听说Bash不了解^(?:\S+\s){1,5}\((\S+):(\d+)\) \d,所以我想到了:

?:

但是当我尝试时:

^([:alpha:]+[:space:]){1,5}\(([:alpha:]+):([0-9]+)\)

我没有任何比赛。我究竟做错了什么?如何编写与Bash兼容的正则表达式来做到这一点?

2 个答案:

答案 0 :(得分:2)

在第一个模式中,您使用myDictionary.Where(d => d.Key >= from && d.Key <= to).Select(d => d.Value).ToArray(); 匹配一个非空格字符。这是一个广泛匹配,并且还将匹配例如\S+,这在第二种模式中没有考虑。

模式以/开头,但第一个字符为0。您可以改用[:alpha:]。由于重复也应匹配[:alnum:],因此也可以添加。

请注意,当对捕获组使用量词时,该组将捕获迭代的最后一个值。因此,在使用_时,您只能将该量词用于重复。其值为{1,5}

您可以使用:

some_function

Regex demo | Bash demo

您的代码可能看起来像

^([[:alnum:]_]+[[:space:]]){1,5}\(((/[[:alpha:]]+)+\.[[:alpha:]]):([[:digit:]]+)\)\.$

结果

line1="0xffffffc0006e0584 is in some_function (/path/to/my/file.c:93)."
regex="^([[:alnum:]_]+[[:space:]]){1,5}\(((/[[:alpha:]]+)+\.[[:alpha:]]):([[:digit:]]+)\)\.$"
[[ $line1 =~ $regex ]]
echo ${BASH_REMATCH[2]}
echo ${BASH_REMATCH[4]}

或者使用/path/to/my/file.c 93 的版本短一点,值在组2和3中

\S

说明

  • ^([[:alnum:]_]+[[:space:]]){1,5}\((\S+\.[[:alpha:]]):([[:digit:]]+)\)\.$ 字符串的开头
  • ^重复1-5次在第1组中捕获的内容
  • ([[:alnum:]_]+[[:space:]]){1,5}匹配\(
  • (捕获 group 2 匹配1个以上非空格字符,(\S+\.[[:alpha:]])和一个字母字符
  • .匹配:
  • :捕获第3组匹配1个以上的数字
  • ([[:digit:]]+)匹配\)\.
  • ).字符串结尾

关于bracket expressions的页面见此

Regex demo

答案 1 :(得分:2)

是的,Bash使用POSIX ERE,不支持\d速记字符类,也不支持非捕获组。参见more regex features unsupported in POSIX ERE/BRE in this post

使用

.*\((.+):([0-9]+)\)

或者甚至(如果您需要获取字符串中的第一个(...)子字符串):

\(([^()]+):([0-9]+)\)

详细信息

  • .*-尽可能多的0个字符(可以省略,只有在还有其他(...)个子字符串并且您只需要获取 last 的情况下才需要一个)
  • \(-一个(字符
  • (.+)-组1(${BASH_REMATCH[1]}):尽可能多的1个字符以上
  • :-冒号
  • ([0-9]+)-第2组(${BASH_REMATCH[2]}):1位以上数字
  • \)-一个)字符。

请参见Bash demo(或this one):

test='0xffffffc0006e0584 is in some_function (/path/to/my/file.c:93).'
reg='.*\((.+):([0-9]+)\)'
# reg='\(([^()]+):([0-9]+)\)' # This also works for the current scenario
if [[ $test =~ $reg ]]; then
    echo ${BASH_REMATCH[1]};
    echo ${BASH_REMATCH[2]};
fi

输出:

/path/to/my/file.c
93