簡體   English   中英

python 中多行字符串的條件正則表達式

[英]conditional regex on multiline string in python

這個問題類似於我原來的帖子。

無法使用條件正則表達式來測試 python 中的字符串

發布另一個新問題的原因是這里的要求與原來的要求有點不同。

如果給定的字符串是逐行的,那么原始答案就足夠了。 但是,那里的答案不能涵蓋多行字符串的情況。 見下文

測試用例 測試字符串 期望來自 bool(re.match(...)) 的值
1. 天真的比賽
 xxxx
xxxx
板添加 0/1 aaa
板添加 0/2 aaa
板添加 0/3 bbb
板添加 0/4 bbb
板添加 0/5 aaa
#
真的
2.錯誤的model名字
 xxxx
xxxx
板添加 0/1 xxx
板添加 0/2 aaa
板添加 0/3 bbb
板添加 0/4 aaa
板添加 0/5 bbb
#
錯誤的
3.缺少model
  xxxx
xxxx
板添加 0/2 aaa
板添加 0/3 bbb
板添加 0/4 bbb
板添加 0/5 aaa
#
真的

我嘗試多個正則表達式。 但是,它們都在任一測試用例 (2) / (3) 上都失敗了。

試過正則表達式 測試失敗
(board add 0/1)? (?(1) (aaa|bbb)) 2個
^(?:(?.board add 0/1)?)*$|board add 0/1 (::aaa|bbb) 2個
board add 0/1 (aaa|bbb) 3個
(?=board add 0/1 )(?:board add 0/1 (aaa|bbb)) 3個

是否可以編寫一個正則表達式來獲得上述測試用例通過?

您可以通過以下url查看它們

https://regex101.com/r/2l2Qd4/1

筆記:

  • 我只想捕捉一個特定的board add 0/1而不是board add 0/\d+
    • 在我的實際用例中,接口可能需要不同的模型。 這就是為什么我試圖找出board add 0/1的特定正則表達式。 然后,我可以將正則表達式擴展到board add 0/2board add 0/21一個接一個
  • 有效字符串的要求
    • 如果board add 0/1存在於字符串中,則它后面必須跟有(aaa|bbb) 否則無效
    • 如果字符串中不存在board add 0/1 ,則這是一個有效字符串。

在這種情況下,您可以使用此正則表達式

board add 0/\d+ (?!aaa|bbb)

如果正則表達式匹配,則該字符串無效。

Python 示例

import re


strings = [
    """xxxx
xxxx
 board add 0/1 aaa
 board add 0/2 aaa
 board add 0/3 bbb
 board add 0/4 bbb
 board add 0/5 aaa
#""",
    """xxxx
xxxx
 board add 0/1 xxx
 board add 0/2 aaa
 board add 0/3 bbb
 board add 0/4 aaa
 board add 0/5 bbb
#""",
    """xxxx
xxxx
 board add 0/2 aaa
 board add 0/3 bbb
 board add 0/4 bbb
 board add 0/5 aaa
#"""
]

for string in strings:
    print(not bool(re.search(r"board add 0/\d+ (?!aaa|bbb)", string)))

Output

True
False
True

解釋

re.search按給定模式返回匹配的字符串塊。 如果不存在任何匹配項,則返回None 該解決方案基於否定有效字符串。 因此,如果在board add 0/1之后既沒有跟隨aaa也沒有跟隨bbb ,則該字符串無效。 rest 按照您在上一個問題中的描述傳遞。 因此,如果re.search返回None以外的任何值,則not bool(...)會將值轉換為預期結果。

注意:我使用的not bool(...) ,因為如果字符串不包含模式,則它是有效的。

在這個問題中,我們可以只關注 board add 0/1 而忽略其他 board add 0/x 。 事實上,盡管有否定,但您當前的解決方案符合我的需要。 我只是想知道為什么我們需要否定,為什么我的回答不起作用。

第一個(board add 0/1)? (?(1) (aaa|bbb)) (board add 0/1)? (?(1) (aaa|bbb))我不明白你期望匹配什么。 第二個正則表達式類似於我對您上一個問題的回答。 第三個更接近答案。

我更改了我建議您之前的問題的正則表達式。

^(?:(?!board add 0\/1).)*$|^.*?board add 0\/1 (?:aaa|bbb).*$

現在您可以使用re.match而不是re.search

...

for string in strings:
    print(bool(re.match(r"^(?:(?!board add 0\/1).)*$|^.*?board add 0\/1 (?:aaa|bbb).*$", string, re.S)))

Output

True
False
True

注意:還使用了re.S (單行)標志。

您似乎想要匹配所有以 aaa 或 bbb 結尾的板行,並在以非空白字符開頭的字符串之間縮進。

為防止部分匹配,您需要識別重復板部分之前和之后的部分。

^\S.*(?:\n[^\S\n]+board add 0/\d+ (?:aaa|bbb))+\n\S

解釋

  • ^字符串開始
  • \S.*匹配一個非空白字符和該行的 rest
  • (?:非捕獲組作為一個整體重復
    • \n[^\S\n]+匹配換行符后跟 1+ 個空格
    • board add 0/\d+ (?:aaa|bbb)匹配\d+匹配 1+ 數字的棋盤模式
  • )+關閉非捕獲組,重復1+次至少匹配一行
  • \n\S匹配換行符和非空白字符

正則表達式演示

暫無
暫無

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

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