使用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})"