簡體   English   中英

正則表達式是否可以匹配字符串開頭或結尾的字符(但不能同時匹配)?

[英]Can a regular expression match a character at the beginning OR end of the string (but not both)?

我正在寫一個正則表達式來驗證歐元貨幣字符串。 它允許幾種不同的格式,因為一些語言環境使用小數點作為千位分隔符,一些使用空格,一些將€放在開頭,一些放在最后。 這是我想出的:

/^(€ ?)?\\-?([1-9]{1,3}( \\d{3})*|[1-9]{1,3}(\\.\\d{3})*|(0|([1-9]\\d*)?))(,[0-9]{2})?( ?€)?$/

這適用於以下測試:

有效:

123 456,78
123.456,78
€6.954.231
€896.954.231
16.954.231€
12 346 954 231€
€10.03
10.03
1,39
,03
0,10
€10567,01
€0,01
€1 234 567,89
€1.234.567,89

無效

1,234€1,1
50#,50
123,@€
€€500
0001
€,001
€0.001
12.34,56
123456.123.123456

這樣做的一個問題是它驗證了兩端帶有歐元符號的字符串,例如€123€。 這對我的目的來說可能是可以接受的,但是有沒有辦法制作一個緊湊的RegEx,它只允許一端的字符,而不是兩者,或者我只需要編寫一個兩倍長的字符,首先檢查一個有效的字符串開頭是可選的€,然后是最后一個帶有可選€的有效字符串?

更新接受答案中的答案仍有一些誤報。 我最終編寫了一個函數,它有幾個選項來自定義驗證器。 這是該庫中isCurrency函數。 仍然使用前瞻來避免某些邊緣情況,這是回答這個問題的關鍵。

有了先行,這將起作用

^(?!€*$)(€ ?(?!.*€)(?=,?\d))?\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?( ?€)?$

請參閱: https//regex101.com/r/aR4xR8/8

@Necreaux值得稱贊,首先指出前瞻!

根據您的正則表達式引擎,您可以使用負向前導來執行此操作。

^€(?!(.*€))

您可以使用此模式:

^
(?=(.))          # you capture the first character in a lookahead
(?:€[ ]?)?
(?:
    [1-9][0-9]{0,2}
    (?:
        ([ .]) [0-9]{3} (?: \2 [0-9]{3})*
      |
        [0-9]*
    )
    (?:,[0-9]{2})?
  |
    0?,[0-9]{2}
)

(?:
    [ ]?
    (?!\1)€   # you test if the first character is not an €
)?
$

在線演示

我們的想法是捕獲第一個字符並測試它最后是否相同。

要與javascript一起使用,您需要刪除格式:

var re = /^(?=(.))(?:€ ?)?(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\2[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})(?: ?(?!\1)€)?$/;

關於這種方式:唯一的興趣是短缺。 如果你想要性能,最好的方法是從字面上寫出兩種可能性:

var re = /^(?:€ ?(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\1[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})|(?:[1-9][0-9]{0,2}(?:([ .])[0-9]{3}(?:\2[0-9]{3})*|[0-9]*)(?:,[0-9]{2})?|0?,[0-9]{2})(?: ?€)?)$/;

寫入時間更長,但它減少了正則表達式引擎的工作。

使用支持PCRE等條件子模式的正則表達式引擎,您可以這樣寫:

\A
(€ ?)?
(?:
    [1-9][0-9]{0,2}
    (?: ([ .]) [0-9]{3} (?:\2[0-9]{3})* | [0-9]*)
    (?:,[0-9]{2})?
  | 
    0?,[0-9]{2}
)
(?(1)| ?€)
\z

其中(?(1)| ?€)if..then..else(?(condition)true|false) ,用於檢查是否定義了捕獲組1。

你可以將你的正則表達式分成兩個派對並將它們與'|'結合起來。 最后一個用€和另一個用於€的東西。

/(^(€ ?)?\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?$)|(^\-?([1-9]{1,3}( \d{3})*|[1-9]{1,3}(\.\d{3})*|(0|([1-9]\d*)?))(,[0-9]{2})?( ?€)?$)/

編輯:

我錯過了你的最后一句話。 我認為最簡單的是將正則表達式編寫兩次。

這是我能夠來的最接近的。 它使用負向前瞻來確保字符串不以歐元符號開頭和結尾:

^(?!€.*€$)€?\s*(0|[1-9][0-9]{0,2})?([. ]?[0-9]{3})*(,[0-9]{2})?\s*€?$

有關完整說明和示例, 請參閱此處的Regex 101 Demo 正如你所看到的,它通過了你所有的測試,但它讓一些不好的測試通過了。 我確定數字部分可以調整,以便它適合你。 確保沒有兩個歐元符號的部分就是這樣:

^(?!€.*€$)€?\s*<digit validation goes here>\s*€?$

負向前瞻確保字符串不以歐元符號開頭和結尾,然后在開始時檢查可選的歐元符號,后跟任意數量的空格,驗證數字,然后檢查任意數量的空格和歐元符號在末尾。

暫無
暫無

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

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