【问题标题】:splitting strings using re.split使用 re.split 分割字符串
【发布时间】:2014-02-17 22:48:23
【问题描述】:

我有多个字符串 (>1000) 的形式:

\r\nSenor Sisig\nThe Chairman\nCupkates\nLittle Green Cyclo\nSanguchon\nSeoul on Wheels\nKasa Indian\n\nGo Streatery\nWhip Out!\nLiba Falafel\nGrilled Cheese Bandits\r\n

字符串可能在'\n'之前有一个空格

如何拆分这些字符串(以一种有效的方式)以避免得到任何空的或重复的(空白大小写)元素?

我正在使用:

re.split(r'\r|\n', str)

编辑: 更多示例:

\r\nThe Creme Brulee Cart \r\nCurry Up Now\r\nKoJa Kitchen\r\nAn the Go\r\nPacific Puffs\r\nEbbett's Good to Go\r\nFiveten Burger\r\nGo Streatery\r\nHiyaaa\r\nSAJJ\r\nKinder's Truck\r\nBlue Saigon\r
\r\nThe Chairman\r\nSanguchon\r\nSeoul on Wheels\r\nGo Streatery\r\nStreet Dog Truck\r\nKinder's Truck\r\nYummi BBQ\r\nLexie's Frozen Custard\r\nDrewski's Hot Rod Kitchen\r
\n An the Go \n Cheese Gone Wild \n Cupkates \n Curry Up Now \n Fins on the Hoof\n KoJa Kitchen\n Lobsta Truck \n Oui Chef \n Sanguchon\n Senor Sisig \n The Chairman \n The Rib Whip 

谢谢!

【问题讨论】:

  • 除了\r\n 之外,您的示例字符串都没有在\n 之前显示任何空格。您是否只想像处理\n 一样处理可选的\r\n,还是您正在尝试做一些不同的事情?

标签: python regex django string


【解决方案1】:

除了一个可选的 \r 之外,您的示例没有显示任何“\n 之前的空格”。

如果这就是您想要处理的全部内容,那么不要在\r\n 上拆分,而是在可能的\r 和明确的\n 上拆分:

re.split(r"\r?\n", s)

当然,这是假设您没有任何裸露的 \r 没有 \n 来处理。如果您需要同等处理\r\r\n\n(类似于Python 的通用换行支持...):

re.split(r"\r|\n|(\r\n)", s)

或者,更简单地说:

re.split(r"(\r|\n)+", s)

如果您想删除前导空格、制表符、多个\r 等,您可以在正则表达式中执行此操作,或者只在每个结果上调用lstrip

map(str.lstrip, re.split(r"\r|\n", s))

... 但这会给你留下空元素。您可以将它们过滤掉,但最好只拆分以 \n 结尾的任何空白运行:

re.split(r"\s*\n", s)

这仍然会在开头和结尾留下空元素,因为您的字符串以换行符开头和结尾,这就是 re.split 应该做的。如果要消除它们,可以在解析前strip字符串,也可以在解析后折腾结束值:

re.split(r"\s*\n", s.strip())
re.split(r"\s*\n", s)[1:-1]

我认为最后两个中的一个正是您想要的……但这实际上只是基于您提供的有限信息的猜测。如果没有,那么其他一个(连同它的解释)应该足以让你写出你真正想要的东西。


从您的新示例来看,您真正想要拆分的是任何包含至少一个\n 的空格。并且您的输入在开头和结尾可能有也可能没有换行符(您的第一个示例两者都有,您的第二个示例开头有\r\n,但结尾没有...),如果有,您想忽略它们。所以:

re.split(r"\s*\n\s*", s.strip())

然而,在这一点上,可能值得问一下为什么你试图将其解析为字符串而不是文本文件。假设您从某个文件或类似文件的对象中获得这些,而不是这样:

with open(path, 'r') as f:
    s = f.read()
    results = re.split(regexpr, s.strip())

…这样的东西可能更具可读性,而且速度也足够快(可能不如最佳正则表达式快,但仍然如此之快,以至于任何浪费的字符串处理时间都被实际文件读取时间所淹没) :

with open(path, 'r') as f:
    results = filter(None, map(str.strip, f))

特别是如果你只想遍历这个列表一次,在这种情况下(假设 Python 3.x,或者使用 ifilterimap 来自 itertools 如果 2.x)这个版本没有将整个文件读入内存并在开始实际工作之前对其进行处理。

【讨论】:

  • @user2216194:好的,再编辑一次,然后告诉我它是否符合您的要求……
  • 我从 facebook graph api (从在描述中列出供应商的事件页面)得到这个,所以我不想要额外的存储空间。问题是描述不一致,所以我的解决方案(或建议的解决方案)适用于某些事件,但不是全部。
  • @user2216194:图 API 真的会返回一个像这样的巨大字符串吗?如果是这样……那很糟糕,但这不是你的错。 :)
【解决方案2】:
re.split(r'[\s\n\r]+', str.strip())

【讨论】:

    【解决方案3】:
    >>> s = "\r\nSenor Sisig\nThe Chairman\nCupkates\nLittle Green Cyclo\nSanguchon\nSeoul on Wheels\nKasa Indian\n\nGo Streatery\nWhip Out!\nLiba Falafel\nGrilled Cheese Bandits\r\n"
    >>> [x for x in s.strip("\r\n").split("\n") if x]
    ['Senor Sisig', 'The Chairman', 'Cupkates', 'Little Green Cyclo', 'Sanguchon', 'Seoul on Wheels', 'Kasa Indian', 'Go Streatery', 'Whip Out!', 'Liba Falafel', 'Grilled Cheese Bandits']
    

    如果你坚持使用正则表达式

    >>> import re
    >>> re.split(r"[\r\n]+", s.strip("\r\n"))
    ['Senor Sisig', 'The Chairman', 'Cupkates', 'Little Green Cyclo', 'Sanguchon', 'Seoul on Wheels', 'Kasa Indian', 'Go Streatery', 'Whip Out!', 'Liba Falafel', 'Grilled Cheese Bandits']
    

    【讨论】:

    • 这适用于他的示例,但这只是因为他的示例实际上并没有说明问题。您没有去除他询问的\n 之前的额外“空白”。
    • 嗯?你的意思是像[x.strip() for x in s.strip("\r\n").split("\n") if x]
    • 也许……但在他澄清他的实际要求(或者,更好的是,给出一个实际证明它的例子)之前,“也许”真的是任何人都可以说的最好的……
    【解决方案4】:

    只过滤掉空值

    list(ifilter(None, re.split(r"\r|\n", your_string)))
    

    Python 正则表达式为您提供 \s -character 类,它匹配 [ \t\n\r\f\v] 中的任何空格(除非设置了 UNICODE 标志,否则它取决于所使用的字符数据库)。

    正如其他答案 (@abarnert) 中所述,您的正则表达式可以\s*\n,即 0 个或多个以 \n 结尾的空格。下面是一个例子。

    In [1]: import re 
    
    In [2]: from itertools import ifilter
    
    In [3]: my_string = """\r\nSenor Sisig \nThe Chairman\nCupkates\nLittle Green Cyclo\nSanguchon\nSeoul on Wheels\nKasa Indian\n\nGo Streatery\nWhip Out!\nLiba Falafel\nGrilled Cheese Bandits\r\n"""
    
    In [4]: list(ifilter(None, re.split(r"\s*\n", my_string)))
    Out[4]: 
    ['Senor Sisig',
     'The Chairman',
     'Cupkates',
     'Little Green Cyclo',
     'Sanguchon',
     'Seoul on Wheels',
     'Kasa Indian',
     'Go Streatery',
     'Whip Out!',
     'Liba Falafel',
     'Grilled Cheese Bandits']
    

    请注意,我使用的是来自itertools packageifilter。您可以使用filter 或列表组合。

    像这样:

    [x for x in re.split("\s*\n", my_string) if x]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 1970-01-01
      • 2022-11-23
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多