【问题标题】:What characters need to be escaped in this regular expression string?在这个正则表达式字符串中需要转义哪些字符?
【发布时间】:2019-05-05 18:28:19
【问题描述】:

我正在尝试在两个标签 <example>text</example> 之间提取文本。我找到了一个可以使用正则表达式来做到这一点的帖子;但是,当我尝试在 Python 中使用它时,我不得不转义字符。

original regex : run = re.findall("(?<=(<runs>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]"'+–/\/®°⁰!?{}|`~]| )+?(?=(</runs>))", text)

完整代码:

#text is a text file but there is too much data to process to post it here
text = "<os>Windows Vista or Windows 7</os><filename>AS_ENGINE.EXE</filename><header_size>240</header_size><atime>2019-04-28T13:34:34Z</atime><runs>1</runs><filenames><file>
<os>Windows Vista or Windows 7</os><filename>CHRMSTP.EXE</filename><header_size>240</header_size><atime>2019-04-28T13:15:32Z</atime><runs>2</runs><filenames>
<os>Windows Vista or Windows 7</os><filename>RUNDLL32.EXE</filename><header_size>240</header_size><atime>2019-04-28T13:07:35Z</atime><runs>1</runs><filenames><file>"

soup = BeautifulSoup(text, "lxml")

          for x in soup.find_all("runs"):
            print("Orginal ", x)

          for x in soup.find_all("dir"):
            print("Orginal ", x)

           for x in soup.find_all("filename"):
            print("Orginal ", x)

然后我想将某些标签写入 csv...


fieldnames = 'File Nmae','Number of runs','File Path'
    with open("C:\\ProgramData\\processed\\winprefetch.csv", 'w', newline='', encoding="utf8") as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(fieldnames)
        writer.writerows([[diskimage_name * row], filename, numberofruns,file]

【问题讨论】:

    标签: python regex escaping


    【解决方案1】:

    Parsing XML with regex is a poor approach。 Python 有一个名为 Beautiful Soup 的 XML 解析库,可以准确地执行此任务:

    from bs4 import BeautifulSoup
    
    text = '<filename>MPSIGSTUB.EXE</filename><header_size>240</header_size><atime>2019-04-28T13:34:33Z</atime><runs>1</runs><filenames><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CNTDLL.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CKERNEL32.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CAPISETSCHEMA.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CKERNELBASE.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CLOCALE.NLS</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD\x5CINSTALL\x5CMPSIGSTUB.EXE</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CADVAPI32.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CMSVCRT.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CSECHOST.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CRPCRT4.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CVERSION.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CCRYPTBASE.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CTEMP\x5CMPSIGSTUB.LOG</file></filenames><volume><path>\x5CDEVICE\x5CHARDDISKVOLUME1</path><creation>2019-04-28T22:00:18Z</creation><serial_number>84c53be0</serial_number><dirnames><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5C$EXTEND</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD\x5CINSTALL</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CTEMP</dir></dirnames></volume>'
    
    soup = BeautifulSoup(text, "lxml")
    
    print(soup.find("runs").text)
    
    for x in soup.find_all("dir"):
        print(x) # or x.text if you're only interested in the element contents
    

    输出:

    1
    <dir>\DEVICE\HARDDISKVOLUME1\$EXTEND</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS\SOFTWAREDISTRIBUTION</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS\SOFTWAREDISTRIBUTION\DOWNLOAD</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS\SOFTWAREDISTRIBUTION\DOWNLOAD\INSTALL</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS\SYSTEM32</dir>
    <dir>\DEVICE\HARDDISKVOLUME1\WINDOWS\TEMP</dir>
    

    【讨论】:

    • 这太棒了@ggorlen!有没有办法只获取标签之间的数字或目录?所以&lt;run&gt;1&lt;/runs&gt;返回1
    • 使用.text 访问元素的文本。
    • 当我使用print(soup.find_all("runs").text) 时我不工作我收到以下错误:ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key AttributeError: ResultSet object has no attribute 'text'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?"
    • find_all 返回一个列表。使用[x.text for x in soup.find_all("runs")] 或在find_all 返回的列表上编写for 循环,就像我在上面的示例中所做的那样。
    • 好吧,你已经完全改变了你的问题,这里的答案无效。我不建议这样做——您应该回滚编辑并使用导致新问题的代码提出关于 BeautifulSoup 的新问题。
    【解决方案2】:

    试试这个:

    import re
    text ="<filename>MPSIGSTUB.EXE</filename><header_size>240</header_size><atime>2019-04-28T13:34:33Z</atime><runs>1</runs><filenames><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CNTDLL.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CKERNEL32.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CAPISETSCHEMA.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CKERNELBASE.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CLOCALE.NLS</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD\x5CINSTALL\x5CMPSIGSTUB.EXE</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CADVAPI32.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CMSVCRT.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CSECHOST.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CRPCRT4.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CVERSION.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32\x5CCRYPTBASE.DLL</file><file>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CTEMP\x5CMPSIGSTUB.LOG</file></filenames><volume><path>\x5CDEVICE\x5CHARDDISKVOLUME1</path><creation>2019-04-28T22:00:18Z</creation><serial_number>84c53be0</serial_number><dirnames><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5C$EXTEND</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSOFTWAREDISTRIBUTION\x5CDOWNLOAD\x5CINSTALL</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CSYSTEM32</dir><dir>\x5CDEVICE\x5CHARDDISKVOLUME1\x5CWINDOWS\x5CTEMP</dir></dirnames></volume>"
    #regx
    find = re.findall("(?<=(<runs>))(\w|\d|\n|[().,\-:;@#$%^&*\[\]\"'+–/\/®°⁰!?{}|`~]| )+?(?=(</runs>))", text)
    print(find)
    

    您非常接近 - 看起来您在使用 "s 时遇到了问题。另外,我认为正则表达式可以简化,虽然我不知道你的问题的细节。例如:

    import re
    text ="<filename>MPSIGSTUB.EXE</filename><runs>0</runs>asdf<runs>1</runs>"
    #regx
    matches = re.finditer("<runs>(.*?)</runs>", text)
    for match in matches:
        print(match.group(1))
    # output: 
    # 0
    # 1
    

    【讨论】:

    • 嗨@Cam,您的示例确实有效,但是当我尝试将其应用于我的代码时它不会正确返回,我将更新上面的代码以向您展示完整的图片。
    猜你喜欢
    • 1970-01-01
    • 2018-11-22
    • 2011-07-25
    • 2010-09-21
    相关资源
    最近更新 更多