我想问一些匹配0次模式的例子是否有用?
我对this问题的理解是,它还用于捕获空字符串以及> 0个出现的字符串(或字符)。有使用的实际例子,以便我可以更好地理解直觉吗?
答案 0 :(得分:3)
如果您想查看所使用的*
量词的真实示例。只是看看堆栈溢出!找到一个回答很多正则表达式问题的人,例如Wiktor Stribiżew,并在其答案中搜索*
的用法。这是我的answer,它使用*
。
*
的一个非常常见的用例是匹配可选的空格。通常,当您要求用户输入内容时,您希望尽可能宽松(用户可以添加任意数量的空格,或者完全不添加空格),而不是遵循非常严格的语法。
例如,电话号码。我住的地方的电话号码是8位数字,它们以4为一组进行分组。例如
1234 5678
为了尽可能宽松,可以使用这样的正则表达式:
^\s*(\d{4})\s*(\d{4})\s*$
看到使用*
吗?它允许任何数量(包括0)的尾部,前导空格和中间空格。即使用户不小心在中间输入了两个空格,程序仍然可以理解它们。
正则表达式可以匹配所有这些
1234 5678
12345678
1234 5678
1234 5678
或者我可以更加宽容,并在各处留出空间:
^(?:\s*\d\s*){8}$
无论如何,有一天您认为不需要的事情会在您需要的时候派上用场。当我学习如何编码时,我曾经想过“这种语言功能是没有用的”,但是当我实际编写代码来解决问题时,我常常会开始使用那些我认为“无用”的功能。在适合使用*
的地方,您只是没有遇到问题。
答案 1 :(得分:1)
为了扩展对{0}
量词的评论... Ruby的Onigmo是功能更丰富的正则表达式引擎之一(尽管它也有缺点,尤其是在Unicode合规性AFAIK中)。非常有趣的一点是,它允许您创建子例程-基本上,以递归方式匹配已定义的命名组。反过来,这几乎可以让您创建一个解析器(尽管我仍然建议在需要解析器时使用Treetop或其他“真正的”解析器库)。
这是一个玩具示例(https://tomassetti.me/ebnf/中Tiny C语法的翻译)。 {0}
用于在定义时不匹配组,仅在\g<name>
构造显式调用时使用。
tiny_c_re = %r{
(?<program> \g<statement>+){0}
(?<statement>
if \g<paren_expr> \g<statement> (?:else \g<statement>)? |
while \g<paren_expr> \g<statement> |
do \g<statement> while \g<paren_expr> ; |
{ \g<statement>* } |
\g<expr> ; |
;
){0}
(?<paren_expr> \( \g<expr> \) ){0}
(?<expr>
\g<test> |
\g<id> = \g<expr>
){0}
(?<test> \g<sum> (?: < \g<sum> )? ){0}
(?<sum> \g<term> (?: [+-] \g<term> )? ){0}
(?<term> \g<id> | \g<integer> | \g<paren_expr> ){0}
(?<id> \g<string> ){0}
(?<integer> \g<int> ){0}
(?<string> [a-z]+ ){0}
(?<int> [0-9]+ ){0}
^ \g<program> $
}x
good = <<EOF
count = 5;
sum = 0;
while (0 < count) {
sum = sum + count;
count = count - 1;
}
EOF
puts good.gsub(/[ \r\n\t]+/, '') =~ tiny_c_re ? "Correct" : "Syntax error"
# => Correct
bad = <<EOF
count = 5;
sum = 0;
while (0 < count) {
sum = = sum + count;
count = count - 1;
}
EOF
puts bad.gsub(/[ \r\n\t]+/, '') =~ tiny_c_re ? "Correct" : "Syntax error"
# => Syntax error