如何只打印文本块中匹配的正则表达式字符串?

时间:2017-03-23 13:45:11

标签: python regex

我的最终目标是输入一个包含域的文本块(多行),并输出一个域列表。

示例输入:

2017-03-02:  173.254.221.115 port 80 - www.hlowdolax.top - GET /usp?f=1if
2017-03-02:  173.254.221.115 port 80 - www.hjaoopoa.top - GET /uf=1if
2017-03-04:  173.254.221.115 port 80 - www.foolalexas.top - GET /userif
2017-03-04:  54.202.16.39 port 80 - pentsshoperqunity.top - 

在这种情况下我想要的输出:

www.hlowdolax.top
www.hjaoopoa.top
www.foolalexas.top
pentsshoperqunity.top

最终我发现用于此目的的最佳工具是re.findall(),并试图这样做:

matchedDomains=re.findall(myRegex, fileWithMessyText.read())
print matchedDomains

在输出中我看到它匹配所有域但结果如下:

[('www', 'hlowdolax', 'to', 'p'), ('user', 'p', 'h', 'p'), ('1', 'g', 'i', 'f'), ('www', 'hjaoopoa', 'to', 'p'), ('user', 'p', 'h', 'p'), ('1', 'g', 'i', 'f'), ('www', 'foolalexas', 'to', 'p'), ('user', 'p', 'h', 'p'), ('1', 'g', 'i', 'f'), ('pentsshoperqunity', 't', 'o', 'p'), ('search', 'p', 'h', 'p'), ('nikesportweardewvv', 't', 'o', 'p'), ('search', 'p', 'h', 'p'), ('www', 'dpooldoopl', 'a', 'top'), ('user', 'p', 'h', 'p'), ('1', 'g', 'i', 'f'), ('fordfocuscommunoityesz', 't', 'o', 'p'), ('www', 'sosgenerga', 'lz', 'top'), ('user', 'p', 'h', 'p'), ('1', 'g', 'i', 'f'), ('fordfocuscommunoityesz', 't', 'o', 'p'), ('search', 'p', 'h', 'p')]

如果相关,这是我使用的正则表达式:

([A-Za-z0-9]{1,})\.([A-Za-z0-9]{1,10})\.?([A-Za-z]{1,})\.?([A-Za-z]{1,})

我搜索了各种关键字,用pythex.org测试了我的正则表达式,并了解了一个术语"匹配捕获"并且它必须对"捕获组"执行某些操作,但我在此处使用group找到的所有建议似乎与findall不兼容,但如果我尝试使用searchmatch它仅适用于第一行并打印整行而不仅仅是匹配(看起来像是漫无目的但我没有记录我的漫游所以我不记得我到底试过了什么。同样直观地说,当有一个匹配整个块的工具时,使用循环并逐行匹配似乎是一种解决方法。问题是,我不知道如何使用它。

我没有找人为我编写代码,但此时我真的迷失了。有没有办法使用findall并输出格式正确的匹配?

6 个答案:

答案 0 :(得分:2)

你的正则表达式中的括号创建捕获组,只需删除它们:

[A-Za-z0-9]{1,}\.[A-Za-z0-9]{1,10}\.?[A-Za-z]{1,}\.?[A-Za-z]{1,}

Here是一个示范。

>>> re.findall(r'[A-Za-z0-9]{1,}\.[A-Za-z0-9]{1,10}\.?[A-Za-z]{1,}\.?[A-Za-z]{1,}', s)
['www.hlowdolax.top', 'www.hjaoopoa.top', 'www.foolalexas.top', 
 'pentsshoperqunity.top']

答案 1 :(得分:0)

您不需要使用regex,而是使用split()

>>> data = '''2017-03-02:  173.254.221.115 port 80 - www.hlowdolax.top - GET /usp?f=1if'''
>>> print(" ".join(data.split()).split()[-4])
www.hlowdolax.top

说明:

首先,您可以从字符串中删除多余的空格,然后将其与单个space拆分,并提供所需的索引-4

答案 2 :(得分:0)

只是不捕捉群组:

myRegex = '(?:[A-Za-z0-9]{1,})\.(?:[A-Za-z0-9]{1,10})\.?(?:[A-Za-z]{1,})\.?(?:[A-Za-z]{1,})'

小组开头的?:说“不要抓住我”。

根据the docs,如果没有捕获组,则返回与该模式匹配的字符串列表。

答案 3 :(得分:0)

使用re.split()import re s = ''' 2017-03-02: 173.254.221.115 port 80 - www.hlowdolax.top - GET /usp?f=1if 2017-03-02: 173.254.221.115 port 80 - www.hjaoopoa.top - GET /uf=1if 2017-03-04: 173.254.221.115 port 80 - www.foolalexas.top - GET /userif 2017-03-04: 54.202.16.39 port 80 - pentsshoperqunity.top - ''' result = [re.split(r'\s+', l)[5] for l in s.strip().split('\n')] print(result) 函数的解决方案:

['www.hlowdolax.top', 'www.hjaoopoa.top', 'www.foolalexas.top', 'pentsshoperqunity.top']

输出:

Sub OpenCSVs_2()
Dim MyFiles As String, ThisMonth As String
Dim startPath As String
Dim wb As Workbook
ThisMonth = Format(Date, "mmmm")
startPath = "C:\Users\ME\Desktop\CSV find convert tests\" & ThisMonth & "\"
MyFiles = Dir(startPath & "*.csv")

Do While MyFiles <> ""

    Set wb = Workbooks.Open(startPath & MyFiles)

    Call Parse1

    wb.SaveAs Filename:=startPath & Replace(MyFiles, ".csv", ".xlsx"), FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False

    MyFiles = Dir

Loop

End Sub

答案 4 :(得分:0)

如果您仍想使用该正则表达式,则应检索每个“完整匹配”。可以使用regex.search()完成。 This documentation会帮助你。它为第一个匹配返回match个对象,其group(0)为完整匹配。 Documentation here。以下是基于您的正则表达式的完整代码。

import re

number = """2017-03-02:  173.254.221.115 port 80 - www.hlowdolax.top - GET /usp?f=1if
2017-03-02:  173.254.221.115 port 80 - www.hjaoopoa.top - GET /uf=1if
2017-03-04:  173.254.221.115 port 80 - www.foolalexas.top - GET /userif
2017-03-04:  54.202.16.39 port 80 - pentsshoperqunity.top -"""

whole = re.compile("([A-Za-z0-9]{1,})\.([A-Za-z0-9]{1,10})\.?([A-Za-z]{1,})\.?([A-Za-z]{1,})")

m = whole.search(number)
output = []
while m:
    t = m.group(0)
    output.append(t)
    m = whole.search(number, number.find(t)+len(t))

print(output)
# ['www.hlowdolax.top', 'www.hjaoopoa.top', 'www.foolalexas.top', 'pentsshoperqunity.top']

答案 5 :(得分:0)

在您的情况下,所有网站都包含在“ - ”中,请尝试以下操作:

number = """2017-03-02:  173.254.221.115 port 80 - www.hlowdolax.top - GET /usp?f=1if
2017-03-02:  173.254.221.115 port 80 - www.hjaoopoa.top - GET /uf=1if
2017-03-04:  173.254.221.115 port 80 - www.foolalexas.top - GET /userif
2017-03-04:  54.202.16.39 port 80 - pentsshoperqunity.top -"""

re.findall(r'.*-(.*)-.*',number)