簡體   English   中英

正則表達式匹配完全匹配的子字符串與Python中的約束

[英]Regex matching on full matched substring with constrains in Python

因為這是一個正則表達式的問題。 這是一個潛在的重復問題。

考慮那些給定的字符串

test_str = [
    "bla bla google.com bla bla", #0
    "bla bla www.google.com bla bla", #1
    "bla bla api.google.com bla bla", #2
    "google.com", #3
    "www.google.com", #4
    "api.google.com", #5
    "http://google.com", #6
    "http://www.google.com", #7
    "http://api.google.com", #8
    "bla bla http://www.google.com bla bla", #9
    "bla bla https://www.api.google.com bla bla" #10
]

我想要的回報是google.*www.google.*但不是api.google.* 這意味着,在上述情況下,2,5,8,10不應該返回任何匹配。


我已經嘗試了幾個正則表達式,但我找不到一行正則表達式字符串來執行此任務。 這是我試過的。

re.compile("((http[s]?://)?www\.google[a-z.]*)") # match 1,4,7,9
re.compile("((http[s]?://)?google[a-z.]*)") # match all
re.compile("((http[s]?://)?.+\.google[a-z.]*)") # match except 0,3,6
re.compile("((http[s]?://)?!.+\.google[a-z.]*)") # match nothing

在這里,我正在尋找一種忽略*.google.*除了www.google.*google.* 但是在找到獲取*.google.*的方法時我陷入困境。


PS:我用split()找到了一種O(n ** 2)方法來解決這個問題。

r = re.compile("^((http[s]?://)?www.google[a-z.]*)|^((http[s]?://)?google[a-z.]*)")

for s in test_str:
    for seg in s.split():
        r.findall(seg)

你可以用

(?<!\S)(?:https?://)?(?:www\.)?google\.\S*

請參閱正則表達式演示

細節

  • (?<!\\S) - 前面有一個空格或字符串開頭的位置(注意你也可以在這里使用(?:^|\\s) ,以便更明確)
  • (?:https?://)? - 與https://http://的可選序列匹配的可選非捕獲組
  • (?:www\\.)? 一個可選的非捕獲組,匹配www.的可選序列www.
  • google\\. - 一個google.
  • \\S* - 0+非空白字符。

Python演示

import re
test_str = [
    "bla bla google.com bla bla", #0
    "bla bla www.google.com bla bla", #1
    "bla bla api.google.com bla bla", #2
    "google.com", #3
    "www.google.com", #4
    "api.google.com", #5
    "http://google.com", #6
    "http://www.google.com", #7
    "http://api.google.com", #8
    "bla bla http://www.google.com bla bla", #9
    "bla bla https://www.api.google.com bla bla", #10
    "bla bla https://www.map.google.com bla bla" #11
]
r = re.compile(r"(?<!\S)(?:https?://)?(?:www\.)?google\.\S*")
for i,s in enumerate(test_str):
    m = r.search(s)
    if m:
        print("{}\t#{}".format(m.group(0), i))

輸出:

google.com  #0
www.google.com  #1
google.com  #3
www.google.com  #4
http://google.com   #6
http://www.google.com   #7
http://www.google.com   #9

如果我的鍵盤工作正常,我會在半小時前回答。

無論如何,我建議不要誇大正則表達式的復雜性。 您可以使用宿主語言來管理黑色(甚至是白色)列表並使用re模塊輔助。 以下是我在腳本中打包的內容。 顯然,如果必須將此代碼集成到類或函數中,則可能需要進行一些重組:

import re

def main():
    input_urls = [ 
        "bla bla google.com bla bla",
        "bla bla www.google.com bla bla",
        # ...
    ]   
    filtered_urls = set()

    google_re = re.compile("(\w+\.)?google.com")
    blacklist = set(["api."])   # I didn't research enough to remove the dot

    for url in input_urls:
        # Beware of the difference between match() and search()
        # See https://docs.python.org/3/library/re.html#search-vs-match
        match = google_re.search(url)

        # The second condition will not be evaluated if the first fails
        if match is not None and match.group(1) not in blacklist:
            filtered_urls.add(url)

    print("Accepted URLs:", *filtered_urls, sep="\n\t", end="\n\n")
    print("Blacklisted URLs:", *(set(input_urls).difference(filtered_urls)), sep="\n\t")


if __name__ == "__main__":
    main()

遺憾的是,由於我的ah鍵盤按鍵不起作用,我無法快速找到刪除網址位置的方法(例如api.googlewww.googlecalendar.google等)。 我強烈建議這樣做。

我的控制台上顯示的輸出是:

None@vacuum:~$ python3.6 ./filter.py 
Accepted URLs:
    http://google.com
    bla bla google.com bla bla
    bla bla www.google.com bla bla
    http://www.google.com
    google.com
    www.google.com
    bla bla http://www.google.com bla bla

Blacklisted URLs:
    api.google.com
    bla bla api.google.com bla bla
    http://api.google.com
    bla bla https://www.api.google.com bla bla

暫無
暫無

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

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