【问题标题】:string manipulation in python to extract specific fieldspython中的字符串操作以提取特定字段
【发布时间】:2020-05-11 13:40:16
【问题描述】:

我在一个文件中有一些数据,其中包含一些用户详细信息,示例行如下

<User id="123" directoryId="122" userName="vik_username" lowerUserName="vik_username" active="1" createdDate="2013-12-01 08:25:34.451" updatedDate="2014-01-20 19:45:49.133" firstName="Vik" lowerFirstName="vik" lastName="GG" lowerLastName="gg" displayName="Vik GG" lowerDisplayName="vikgg" emailAddress="vikgg@vik.com" lowerEmailAddress="vikgg@vik.com">

我想用python写一个脚本并提取以下字段 1.用户名--userName="vik_username" 2. 邮箱地址——emailAddress="vikgg@vik.com" 3.显示名称——displayName="Vik GG" 4.活跃状态——active="1"

我写了一个这样的 python 脚本,我在 '" ' 上拆分双引号,后跟空格。

f = open("users.txt", "r")
user_array=[]
for x in f:
    y=x.split('" ')
    user_array.append(y)

这给了我一个名为 user_array 的数组,它将每个用户的详细信息作为一个数组。

print user_array[0]

返回

['<User id="123', 'directoryId="122', 'userName="vik_username', 'lowerUserName="vik_username', 'active="1', 'createdDate="2013-12-01 08:25:34.451', 'updatedDate="2014-01-20 19:45:49.133', 'firstName="Vik', 'lowerFirstName="vik', 'lastName="GG', 'lowerLastName="gg', 'displayName="Vik GG', 'lowerDisplayName="vikgg', 'emailAddress="vikgg@vik.com', 'lowerEmailAddress="vikgg@vik.com">\n']

现在获取我想要的字段 1.用户名--userName="vik_username" 2. 邮箱地址——emailAddress="vikgg@vik.com" 3.显示名称——displayName="Vik GG" 4.活跃状态——active="1"

我必须做类似的事情 print(user_array[0][&lt;&lt;index of my field&gt;&gt;]) 然后再次拆分以删除字段标签 例如 userName="vik_username 我需要删除 userName="

有人可以帮助我在 python 中以更有效的方式做到这一点吗? 提前致谢。

【问题讨论】:

    标签: python arrays string scripting


    【解决方案1】:

    你可以使用正则表达式:

    import re
    
    string = r'<User id="123" directoryId="122" userName="vik_username" lowerUserName="vik_username" active="1" createdDate="2013-12-01 08:25:34.451" updatedDate="2014-01-20 19:45:49.133" firstName="Vik" lowerFirstName="vik" lastName="GG" lowerLastName="gg" displayName="Vik GG" lowerDisplayName="vikgg" emailAddress="vikgg@vik.com" lowerEmailAddress="vikgg@vik.com">'
    re.findall(r'\"(.*?)\"', string)
    
    >>> ['123', '122', 'vik_username', 'vik_username', '1', '2013-12-01 08:25:34.451', '2014-01-20 19:45:49.133', 'Vik', 'vik', 'GG', 'gg', 'Vik GG', 'vikgg', 'vikgg@vik.com', 'vikgg@vik.com']
    

    表达式 \"(.*?)\" 捕获 (()) 以引号 (\") 开头和结尾且中间有 0 个或多个字符 (.*?) 的所有内容。

    或者,如果您不想使用正则表达式,您可以执行string.split('\"')[1::2] 之类的操作,在引号中拆分但跳过所有不需要的内容:[1::2] 位从列表中的第二项 (1) 开始,每隔一个 (::2) 获取一次。

    然后你可以从返回值中获取任何你想要的项目。


    使用 Jupyter 魔法进行快速性能检查:

    %timeit -n 100000 string.split('\"')[1::2]
    >>> 1.07 µs ± 40.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    
    %timeit -n 100000 re.findall(r'\"(.*?)\"', string)
    >>> 4.65 µs ± 30.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    

    所以如果这些微秒对你来说很重要,我实际上建议你切片而不是使用正则表达式。

    【讨论】:

    • 感谢有关此性能的说明,我的用例是每天可能只增加 2-3 次额外数据,因此在我的情况下性能不会有太大挑战,但我会牢记笔记。也感谢您的详细解释。
    【解决方案2】:

    由于您的数据看起来像 XML 或其他标记,我建议您使用现成的解析器,例如 lxml。如果您在输入字符串中添加结束标记(如果它不存在),您将能够将其解释为 XML:

    from lxml import etree
    
    s = '<User id="123" directoryId="122" userName="vik_username" lowerUserName="vik_username" active="1" createdDate="2013-12-01 08:25:34.451" updatedDate="2014-01-20 19:45:49.133" firstName="Vik" lowerFirstName="vik" lastName="GG" lowerLastName="gg" displayName="Vik GG" lowerDisplayName="vikgg" emailAddress="vikgg@vik.com" lowerEmailAddress="vikgg@vik.com">'
    s +='</User>'
    myxml = etree.fromstring(s)
    d = myxml.attrib
    
    print(d) # Dictionary for further processing
    print(d.values()) # The list of values in a dictionary
    

    我希望这会有所帮助!

    编辑

    Python 还有一个内置的xml 模块,具有相同的功能:

    import xml.etree.ElementTree as ET
    
    s = '<User id="123" directoryId="122" userName="vik_username" lowerUserName="vik_username" active="1" createdDate="2013-12-01 08:25:34.451" updatedDate="2014-01-20 19:45:49.133" firstName="Vik" lowerFirstName="vik" lastName="GG" lowerLastName="gg" displayName="Vik GG" lowerDisplayName="vikgg" emailAddress="vikgg@vik.com" lowerEmailAddress="vikgg@vik.com">'
    s +='</User>'
    myxml = ET.fromstring(s)
    d = myxml.attrib
    
    print(d)
    print(d.values())
    

    【讨论】:

      【解决方案3】:
      import re
      line = """<User id="123" directoryId="122" userName="vik_username" lowerUserName="vik_username" active="1" createdDate="2013-12-01 08:25:34.451" updatedDate="2014-01-20 19:45:49.133" firstName="Vik" lowerFirstName="vik" lastName="GG" lowerLastName="gg" displayName="Vik GG" lowerDisplayName="vikgg" emailAddress="vikgg@vik.com" lowerEmailAddress="vikgg@vik.com">"""
      
      wanted_tags = ("userName", "emailAddress", "displayName", "active")
      tag_contents = [re.search(fr'{tag}="(.*?)"', line).group(1) for tag in wanted_tags]
      # ['vik_username', 'vikgg@vik.com', 'Vik GG', '1']
      

      我们通过正则表达式匹配给定的标签及其内容。 您可以自定义wanted_tags,结果列表tag_contents 将依次对应wanted_tags 的信息。如果你愿意,你可以用这 2 个做字典。

      【讨论】:

        猜你喜欢
        • 2021-11-08
        • 1970-01-01
        • 2020-05-11
        • 1970-01-01
        • 2017-12-04
        • 2020-08-20
        • 2019-02-19
        • 1970-01-01
        • 2012-07-06
        相关资源
        最近更新 更多