我在 bash 脚本中的正则表达式中匹配 ASCII 代码时遇到了麻烦。
我的有效负载是:payload='#1243669, start 2018-12-17 16:32:50 CET'
我的旧正则表达式是:regold='(#[^,]+),'
我的新正则表达式是:regnew='(#[^\x2c]+)\x2c'
当我在 shell 中进行测试时,它确认新的正则表达式不起作用,而它在 regex101.com 上起作用:
root@test# payload='#1243669, start 2018-12-17 16:32:50 CET'
root@test# regold='(#[^,]+),'
root@test# regnew='(#[^\x2c]+)\x2c'
root@test# if [[ $payload =~ $regold ]]; then echo yes; fi
yes
root@test# if [[ $payload =~ $regnew ]]; then echo yes; fi
编辑:
通过告诉 bash 不支持 PCRE 表达式来部分回答问题。所以我将我的正则表达式移至此:
root@test# regex=$'(\x23[^\x2c]+)\x2c[[:space:]]start[[:space:]][[:digit:]]{4}\x2d[[:digit:]]{2}\x2d[[:digit:]]{2}[[:space:]]([^[:space:]]+)[[:space:]][^\x2c]+\x2c[^\x2c]+\x2c[[:space:]](captureme)'
root@test# pattern='Message #1243669, start 2018-12-17 16:32:50 CET, duration 20, captureme'
同样,我的表达式在 regex101 上效果很好,示例在这里https://regex101.com/r/g4UsUN/1
表达到此为止:... [[:space:]][^\x2c]+ ...但是当我添加 \x2c 时 bash 遇到了一些困难
这是怎么回事 ?
答案1
在 中bash
,您可以插入十六进制代码为 的代码的文字字符$'\xHH'
。 bash
否则将无法识别字符串中的它们,并且正则表达式[^\x2c]
将匹配任何不是\
、x
、2
或 的字符c
。regex101.com
您测试表达式的网站可能使用了 PCRE 正则表达式引擎。这不是bash
用途,它使用 POSIX 扩展正则表达式(该网站似乎不支持)。这也意味着bash
不支持您在 PCRE 中使用的其他正则表达式语法,例如\d
数字、\s
空格字符、前瞻或类似内容。
POSIX 正则表达式(基本的和扩展的)应该在您的系统上记录在re_format(7)
手册 ( man 7 re_format
) 中,并且还由POSIX 标准。
因此,使用
regnew=$'#[^\x2c]+\x2c'
(括号好像没用过,所以我把它去掉了)。由于bash
在将字符串分配给变量之前会扩展转义序列,并且由于它们可能扩展为在正则表达式中可能具有特殊含义的字符,因此必须小心转义转义序列以匹配文字值。例如,当要匹配文字点时,可能需要\x2e
在(点字符)前面加上\\
( )。\\\x2e
从bash
手册:
该形式的单词
$'string'
经过特殊处理。该单词扩展为字符串,并按照 ANSI C 标准指定的方式替换反斜杠转义字符。反斜杠转义序列(如果存在)按如下方式解码:[...]
\xHH
HH
其值为十六进制值(一位或两位十六进制数字)的八位字符
请注意,使用$'...'
将使 shell 也替换它识别的任何其他转义序列。