Bash =~ 正则表达式和 https://regex101.com/

Bash =~ 正则表达式和 https://regex101.com/

使用https://regex101.com/我构建了一个正则表达式来返回字符串中第一次出现的 IP 地址。

正则表达式:

(?:\d{1,3}\.)+(?:\d{1,3})

包含分隔符的正则表达式:

/(?:\d{1,3}\.)+(?:\d{1,3})/

使用以下测试字符串:

eu-west                       140.243.64.99 

它返回以下内容的完整匹配:

140.243.64.99

无论我尝试使用锚点等,以下 bash 脚本都无法使用生成的正则表达式。

temp="eu-west                       140.243.64.99            "
regexp="(?:\d{1,3}\.)+(?:\d{1,3})"
if [[ $temp =~ $regexp ]]; then
  echo "found a match"
else
  echo "No IP address returned"
fi

答案1

\d是表示“任何数字”的非标准方式。我认为它来自 Perl,许多其他语言和实用程序也支持 Perl 兼容的 RE (PCRE)。 (例如,Debian Stretch 中的 GNU grep 2.27\w即使在正常模式下也支持类似的单词字符。)

但Bash 不支持\d,因此您需要显式使用[0-9][[:digit:]]。对于非捕获组也是如此(?:..),直接使用(..)即可。

这应该打印match

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match

答案2

(:...)\d是 perl 或 PCRE 正则表达式运算符(如 GNU 中的grep -P)。

bash仅支持扩展正则表达式 in ,grep -E但对于按字面传递的正则表达式,如 in ,[[ text =~ regexp-here ]]而不是作为不带引号的扩展的结果(如 in[[ text =~ $var ]][[ test =~ $(printf '%s\n' 'regexp-here') ]]),它仅限于 POSIX 扩展正则表达式功能集。

因此,即使在grep -E '\d'可以工作的系统上(GNU ERE 已经从 perl 正则表达式导入了一些扩展,\s未来的版本也可能有\d),您也必须使用:

regexp='\d'
[[ $text =~ $regexp ]]

让它bash工作([[ $text =~ \d ]]不会)。

对于支持 PCRE 的 shell,您可能需要改用zsh

set -o rematchpcre
[[ $text =~ '(?:\d{1,3}\.)+(?:\d{1,3})' ]]

ksh93 还支持自己的类似 perl 正则表达式的实现(不完全兼容)作为其模式匹配的一部分。在那里,你可以使用:

regexp='~(P)(?:\d{1,3}\.)+(?:\d{1,3})'
[[ $text = $regexp ]]

(请注意,=而不是=~。您将需要使用临时变量,因为如果不这样做,就会出现很多问题)

答案3

网站正则表达式101.com使用 PCRE(查看左上角)作为默认值,并且它缺乏对“扩展”正则表达式语法的支持。这就是“Perl 兼容正则表达式”,它来自 Perl(这是合理预期的)。

在某些情况下,某些工具(如 )支持 PCRE grep -P,但习惯用法中的 bash 正则表达式支持[[…]]仅适用于扩展正则表达式(如grep -E)。

在扩展正则表达式中,不存在非捕获(?…)括号,并且也缺少 \d。您需要使用简单的(…)and [0-9]

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"

相关内容