正则表达式匹配分数而不是日期

时间:2009-12-16 04:51:15

标签: regex

我正在尝试提出一个正则表达式,它将匹配字符串中的分数(1/2)而不是日期(5/5/2005)。任何帮助都会很棒,所有我能想到的是(\ d +)/(\ d +),它们在两个字符串中找到匹配项。在此先感谢您的帮助。

6 个答案:

答案 0 :(得分:9)

假设PCRE,使用负向前瞻和后视:

(?<![\/\d])(\d+)\/(\d+)(?![\/\d])

前瞻(一个(?=)组)说“匹配这些东西,如果它跟着其他东西。”前瞻的内容不匹配。我们否定它((?!)组)以便它 不会匹配我们的分数之后的东西 - 这样,我们与后面的组不匹配。

前瞻的补充是一个后视(一个(?<=)组)反之亦然 - 它匹配的东西,如果它先于其他东西,就像前瞻,我们可以否定它({{1我们可以匹配那些不遵循某些东西的东西。

它们一起确保我们的馏分在其之前或之后没有其他部分的馏分。它对输入数据没有任何其他任意要求。与大多数其他提供的示例不同,它将匹配字符串(?<!)中的分数2/3

如果你的正则表达式使用"te2/3xt"来分隔正则表达式,你必须在其中转义斜杠,或者使用不同的分隔符(Perl的//在这里是个不错的选择)。


编辑:显然,这些正则表达式都不起作用,因为正则表达式引擎回溯并匹配较少的数字以满足正则表达式的要求。当我一直在研究一个正则表达式时,我坐下来决定一个巨大的正则表达式不是答案,我写了一个函数,它使用正则表达式和一些其他工具为我做。你说过你在使用Ruby。这对我有用:

m{}

此函数返回分数的两个部分,但如果是日期(或者没有分数),则返回>> def get_fraction(s) >> if s =~ /(\d+)\/(\d+)(\/\d+)?/ >> if $3 == nil >> return $1, $2 >> end >> end >> return nil >> end => nil >> get_fraction("1/2") => ["1", "2"] >> get_fraction("1/2/3") => nil nil失败但我不知道你是否想要(或需要)通过。在任何情况下,我建议将来,当你在Stack Overflow上询问时,“如何使正则表达式与此匹配?”你应该先退后一步,看看你是否可以使用正则表达式和一些额外的东西来做。正则表达式是一个很好的工具,可以做很多事情,但它们并不总是需要单独使用。


编辑2:

我想出了如何在不使用非正则表达式代码的情况下解决问题,并更新了正则表达式。它应该按预期工作,虽然我还没有测试过。我也继续前进并逃过"1/2/3 and 4/5",因为无论如何你都要这么做。

编辑3:

我刚刚修复了j_random_hacker在我的前瞻和后方指出的错误。我继续看到这个正则表达式的努力程度,证明纯正则表达式解决方案不一定是解决这个问题的最佳方案。

答案 1 :(得分:6)

使用否定lookahead and lookbehind

/(?<![\/\d])(?:\d+)\/(?:\d+)(?![\/\d])/
编辑:我已经修复了我对@j_random_hacker识别出的回溯错误陷阱的回答。作为证据,我提供以下快速和脏的PHP脚本:

<?php
$subject = "The match should include 1/2 but not 12/34/56 but 11/23, now that's ok.";
$matches = array();
preg_match_all('/(?<![\/\d])(?:\d+)\/(?:\d+)(?![\/\d])/', $subject, $matches);
var_dump($matches);
?>

输出:

array(1) {
  [0]=>
  array(2) {
    [0]=>
    string(3) "1/2"
    [1]=>
    string(5) "11/23"
  }
}

答案 2 :(得分:4)

如果您使用Perl或PCRE,Lookahead很棒,但如果它们在您使用的正则表达式引擎中不可用,您可以使用:

(^|[^/\d])(\d+)/(\d+)($|[^/\d])

第二和第三个被捕获的段将是分子和分母。

如果 在Perl正则表达式中使用上述内容,请记住转义/ - 或使用不同的分隔符,例如:

m!(?:^|[^/])(\d+)/(\d+)(?:$|[^/])!

在这种情况下,您可以使用(?:...)来避免保存不感兴趣的带括号的部分。

编辑18/12/2009 Chris Lutz noticed一个棘手的错误是由回溯引起的,这些错误困扰着大多数这些答案 - 我相信现在已经解决了这个问题。

答案 3 :(得分:0)

如果它的行输入你可以尝试

^(\d+)\/(\d+)$

否则可能使用

^(\d+)\/(\d+)[^\\]*.

答案 4 :(得分:0)

这将有效:(?<![/]{1})\d+/\d+(?![/]{1})

答案 5 :(得分:0)

根据您使用的语言,您可能会尝试使用负向预测或后视断言:在perl(?!pattern)中断言/ pattern /不能跟随匹配的字符串。

或者,再次,根据语言和您对上下文的了解,字边界匹配(perl中的\ b)可能是合适的。