这个想法是对 url 的输入模式进行基本检查:
$ ns='abc.def.com'
$ reg_expr="\N*\.(\D{2}|\D{3})$"
$ echo $reg_expr
\N*\.(\D{2}|\D{3})$
$ [[ $ns =~ "$reg_expr" ]] && echo "ok" || echo "no"
no
但是,正则表达式总是失败。在线正则表达式检查相同模式工作正常。
https://regex101.com/r/vXxv1w/1
为什么会出现这种情况?
答案1
那
\N*\.(\D{2}|\D{3})$
是一个 Perl 正则表达式。 bash 的[[ =~ ]]
运算符采用 POSIX 扩展正则表达式,而不是 Perl 正则表达式。
要使用 perl 风格的正则表达式,请使用 zsh 及其rematchpcre
选项:
set -o rematchpcre
[[ $ns =~ '\N*\.(\D{2}|\D{3})$' ]]
现在,该正则表达式没有多大意义。
\N
旨在匹配除换行符之外的任何字符,但除非您设置标志s
(例如使用(?s)
),.
否则无论如何都不会匹配换行符,因此您可以替换\N
为.
。- 位于
<anything>*
正则表达式的开头或结尾是没有意义的,因为它匹配0或更多<anything>
,所以它也不匹配任何东西。[[ $ns =~ '\.(\D{2}|\D{3})$' ]]
功能上是等价的。 \D
匹配除十进制数字之外的任何字符,即 0123456789 或类似 0123456789٠١٢٣٤٥٦٧٨٩0123356789ot德的任何字符。 ८९০১২৩৪৫৬৭৮৯੦੧੨੩੪੫੬੭੮੯૦૧૨૩૪૫૬૭૮૯୦୧୨୩୪୫୬୭୭ ୯௦௧௨௩௪௫௬௭௮௯౦౧౨౩౪౫౬౭౮౯೦೧೨೩೪೫೬೭೮೯൦൧൨൩൪൫൬൭൮ ൯෦෧෨෩෪෫෬෭෮෯๐๑๒๓๔๕๖๗๘๙໐໑໒໓໔໕໖໗໘໙༠༡༢༣༤༥༦༧༨ ༩၀၁၂၃၄၅၆၇၈၉႐႑႒႓႔႕႖႗႘႙០១២៣៤៥៦៧៨៩᠐᠑᠒᠓᠔ ᠕᠖᠗᠘᠙᥆᥇᥈᥉᥊᥋᥌᥍᥎᥏᧐᧑᧒᧓᧔᧕᧖᧗᧘᧙᪀᪁᪂᪃᪄᪅᪆᪇᪈᪉᪐᪑᪒᪓᪔᪕ ᪖᪗᪘᪙᭐᭑᭒᭓᭔᭕᭖᭗᭘᭙᮰᮱᮲᮳᮴᮵᮶᮷᮸᮹᱀᱁᱂᱃᱄᱅᱆᱇᱈᱉᱐᱑᱒᱓᱔᱕ ᱖᱗᱘᱙꘠꘡꘢꘣꘤꘥꘦꘧꘨꘩꣐꣑꣒꣓꣔꣕꣖꣗꣘꣙꤀꤁꤂꤃꤄꤅꤆꤇꤈꤉꧐꧑꧒꧓꧔꧕ ꧖꧗꧘꧙꧰꧱꧲꧳꧴꧵꧶꧷꧸꧹꩐꩑꩒꩓꩔꩕꩖꩗꩘꩙꯰꯱꯲꯳꯴꯵꯶꯷꯸꯹0123456789
答案2
在 的手册页中bash
,有几个段落描述了[[ expression ]]
测试中有效的运算符。正则表达式匹配的一篇说:
还可以使用附加二元运算符 =~,其优先级与 == 和 != 相同。使用时,运算符右侧的字符串被视为 POSIX 扩展正则表达式并进行相应的匹配...
(略过几句话)
如果模式的任何部分被引用,则引用的部分将按字面匹配。这意味着引用部分中的每个字符都与其自身匹配,而不具有任何特殊的模式匹配含义。如果模式存储在 shell 变量中,则引用变量扩展会强制整个模式按字面匹配。
总而言之,在 内部[[ expression ]]
,不要在正则表达式两边加上引号,也不要在包含正则表达式的变量两边加上引号。即使您已指定=~
为比较运算符,引用正则表达式也会将比较更改为纯粹的字符串匹配,例如==
.
最好按照手册页中的参考资料查看支持哪些正则表达式语法。您可能需要使用[[:digit:]]
and[^[:digit:]]
而不是\d
and \D
。 (我可能会弄错,所以你自己检查一下)