簡體   English   中英

正則表達式匹配分數而不是日期

[英]Regular Expression to match fractions and not dates

我正在嘗試提出一個正則表達式,它將匹配一個字符串中的分數(1/2)而不是日期(5/5/2005)。 任何幫助都會很棒,所有我能想到的是(\\ d +)/(\\ d +),它們在兩個字符串中找到匹配項。 先謝謝您的幫助。

假設PCRE,使用負向前瞻和后觀:

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

一個前瞻(一個(?=)組)說“匹配這些東西,如果它跟隨其他東西。” 前瞻的內容不匹配。 我們否定它( (?!)組)以使它與我們的分數之后的東西匹配 - 這樣,我們在后面的內容中不匹配。

前瞻的補充是一個lookbehind(一個(?<=)組)反過來 - 它匹配的東西,如果它先於其他東西,就像前瞻,我們可以否定它( (?<!)組)這樣我們就可以匹配那些不遵循某些東西的東西。

它們一起確保我們的餾分在其之前或之后沒有其他部分的餾分。 它對輸入數據沒有任何其他任意要求。 與大多數其他提供的示例不同,它將匹配字符串"te2/3xt"中的分數2/3

如果你的正則表達式使用// s來分隔正則表達式,你必須在其中轉義斜杠,或者使用不同的分隔符(Perl的m{}在這里是個不錯的選擇)。


編輯:顯然,這些正則表達式都不起作用,因為正則表達式引擎回溯並匹配較少的數字以滿足正則表達式的要求。 當我一直在為一個正則表達式工作時,我坐下來決定可能是一個巨大的正則表達式不是答案,我寫了一個函數,它使用正則表達式和一些其他工具來為我做。 你說過你在使用Ruby。 這對我有用:

>> 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 它失敗了"1/2/3 and 4/5"但我不知道你是否想要(或需要)通過。 在任何情況下,我建議將來,當你在Stack Overflow上詢問時,“如何使正則表達式與此匹配?” 你應該先退后一步,看看你是否可以使用正則表達式和一些額外的東西來做。 正則表達式是一個很好的工具,可以做很多事情,但它們並不總是需要單獨使用。


編輯2:

我想出了如何在不使用非正則表達式代碼的情況下解決問題,並更新了正則表達式。 它應該按預期工作,雖然我還沒有測試過。 我也繼續前進並逃過了/ s,因為無論如何你都要去做。

編輯3:

我剛剛修復了j_random_hacker在我的前瞻和后面指出的錯誤。 我繼續看到這個正則表達式的努力量,作為純正則表達式解決方案不一定是解決這個問題的最佳解決方案的證據。

使用負向前瞻和后視

/(?<![\/\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"
  }
}

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

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

第二和第三個捕獲的段將是分子和分母。

如果使用上面的一個Perl的正則表達式,記得要躲避/秒-或使用不同的分隔符,如:

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

在這種情況下,您可以使用(?:...)來避免保存不感興趣的帶括號的部分。

編輯18/12/2009Chris Lutz注意到由回溯引起的棘手錯誤,這些錯誤困擾着大多數這些答案 - 我相信這現在已經解決了。

如果它的線輸入你可以嘗試

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

否則可能使用這個

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

這將起作用: (?<![/]{1})\\d+/\\d+(?![/]{1})

根據您正在使用的語言,您可能會嘗試使用負向前瞻或后瞻斷言:在perl(?!pattern)中斷言/ pattern /不能跟隨匹配的字符串。

或者,再次,取決於語言,以及您對上下文的任何了解,字邊界匹配(perl中的\\ b)可能是合適的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM