看一下SO上常见的一些正则表达式问题,在我看来,传统的正则表达式语法在很多领域都缺乏人们现在正在寻找它的任务.例如:
通常的答案是不要使用正则表达式,使用正常的条件比较.如果你自己只得到这个数字就好了,但是当你想把这个数字作为一个更长的字符串的一部分来匹配时,那就不那么好了.为什么我们不能编写类似的东西\d{1~31},要么修改正则表达式来进行某种形式的计数,还是让正则表达式引擎在内部将它转换成[1-9]|[12]\d|3[01]?
这导致了一个非常混乱的正则表达式,能够做到这一点会很棒(mytext){Odd}.
我们都知道这是个坏主意,但如果[^ ]操作员不仅限于一个角色,那么这个和类似的任务会更容易.能够这样做真好<name>(.*)[^(</name>)]
非常常见,但正确使用正则表达式非常复杂.如果{IsEmail}可以使用类似的语法,那么每个人都必须重新发明轮子.
我确信还有其他一些也很有用.我不太了解正则表达式的内部结构,知道这些实现有多么容易,或者甚至是否可能.实现某种形式的计数(解决前两个问题)可能意味着它不再是技术上的"正则表达式",但它肯定会有用.
"正则表达式2.0"语法是否可取,技术上可行,是否有人在处理这样的事情?
Gab*_*abe 16
我相信Larry Wall用Perl 6正则表达式覆盖了它.基本思想是用更有用的语法规则替换简单的正则表达式.它们更容易阅读,并且更容易将代码放入以确保您拥有多个匹配项.另外,你可以命名规则IsEmail.我不可能在这里列出所有细节,但足以说,它听起来像你的建议.
以下是http://dev.perl.org/perl6/doc/design/exe/E05.html中的一些示例:
匹配的IP地址:
token quad { (\d**1..3) <?{ $1 < 256 }> }
$str ~~ m/ <quad> <dot> <quad> <dot> <quad> <dot> <quad> /;
Run Code Online (Sandbox Code Playgroud)
匹配嵌套括号:
$str =~ m/ \( [ <-[()]> + : | <self> ]* \) /;
Run Code Online (Sandbox Code Playgroud)
注释:
$str =~ m/ <'('> # Match a literal '('
[ # Start a non-capturing group
<-[()]> + # Match a non-paren (repeatedly)
: # ...and never backtrack that match
| # Or
<self> # Recursively match entire pattern
]* # Close group and match repeatedly
<')'> # Match a literal ')'
/;
Run Code Online (Sandbox Code Playgroud)
And*_*ore 16
不要怪工具,责怪用户.
构建正则表达式以匹配字符串中的模式.就是这样.
它不是为了:
我们应该重新设计螺丝刀,因为它不能钉?不,用锤子.
只需使用适当的工具完成任务.停止使用正则表达式来处理他们不符合条件的任务.
我想匹配1到31之间的数字,我该怎么做?
使用您的语言结构尝试将字符串转换为整数并进行适当的比较.
如何匹配特定字符串的偶数/奇数次出现?
正则表达式不是字符串解析器.但是,如果只需要解析原始字符串的子部分,则可以使用正则表达式提取相关部分.
如何使用正则表达式解析XML?
你没有.根据需要使用XML或HTML解析器.此外,XML解析器无法完成HTML解析器的工作(除非您有完美形成的XHTML文档),反之亦然.
可能它已经存在并且很久以前了.它被称为"语法".有没有听说过yacc和lex?现在需要一些简单的东西.可能看起来很奇怪,正则表达式的强大之处在于它们在现场编写非常简单.
我相信一些(但很大的)专业领域已经有了所需要的东西.我正在考虑XPath语法.
是否有更大的(不限于XML,但仍然很简单)替代方案可以覆盖所有情况?也许你应该看看perl 6 grammars.
所有这些在Perl中都是合理可行的.
要使1..31与正则表达式匹配:
/( [0-9]+ ) (?(?{ $^N < 1 && $^N > 31 })(*FAIL)) /x
Run Code Online (Sandbox Code Playgroud)
生成如下内容[1-9]|[12]\d|3[01]:
use Regexp::Assemble qw( );
my $ra = Regexp::Assemble->new();
$ra->add($_) for (1..31);
my $re = $ra->re; # qr/(?:[456789]|3[01]?|1\d?|2\d?)/
Run Code Online (Sandbox Code Playgroud)
Perl 5.10+使用try来优化替换,因此以下内容应该足够:
my $re = join '|', 1..31;
$re = qr/$re/;
Run Code Online (Sandbox Code Playgroud)
要匹配偶数次出现:
/ (?: pat{2} )* /x
Run Code Online (Sandbox Code Playgroud)
要匹配奇数次出现:
/ pat (?: pat{2} )* /x
Run Code Online (Sandbox Code Playgroud)
模式否定匹配:
/<name> (.*?) </name>/x # Non-greedy matching
/<name> ( (?: (?!</name>). )* ) </name>/x
Run Code Online (Sandbox Code Playgroud)
要获得与电子邮件地址匹配的模式:
use Regexp::Common qw( Email::Address );
/$RE{Email}{Address}/
Run Code Online (Sandbox Code Playgroud)