【问题标题】:Python: Convert tuples from re.findall into string?Python:将元组从 re.findall 转换为字符串?
【发布时间】:2013-06-19 02:54:34
【问题描述】:

我希望读取文本,使用正则表达式查找模式的所有实例,然后打印匹配的字符串。如果我使用 re.search() 方法,我可以成功抓取并打印所需模式的第一个实例:

import re

text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."

match = re.search(r'(cello|Cello)(\W{1,80}\w{1,60}){0,9}\W{0,20}(lillian|Lillian)', text)
print match.group()

不幸的是,re.search() 方法只能找到所需模式的第一个实例,所以我替换为 re.findall():

import re

text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."

match = re.findall(r'(cello|Cello)(\W{1,80}\w{1,60}){0,9}\W{0,20}(lillian|Lillian)', text)
print match

此例程在示例文本中找到目标模式的两个实例,但我找不到打印出现模式的句子的方法。后一段代码的打印功能产生:('Cello', 'with', 'Lillian'), ('Cello', 'yellow', 'Lillian'),而不是我想要的输出: “大提琴是一只与莉莲一起唱歌的黄色鹦鹉。 大提琴是黄色的莉莲。”

有没有办法修改第二段代码以获得所需的输出?我将非常感谢任何人可以就这个问题提供任何建议。

【问题讨论】:

    标签: python regex printing proximity


    【解决方案1】:

    说明

    在这个正则表达式中使用前瞻,它将捕获包含大提琴和莉莲的完整句子。

    (?:(?<=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$))(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$)).*?\.(?=\s|$))

    表达式分解为这些功能组件:

    • (?:(?<=\.)\s+|^). 之后开始匹配这句话,后跟任意数量的空格或字符串的开头
    • ( 启动捕获组 1,它将捕获整个句子
    • (?= 开始展望
      • (?:(?!\.(?:\s|$)).)*? 确保正则表达式引擎不会通过强制它确认 . 后跟空格或字符串结尾来离开这句话
      • \b匹配单词break
      • [Cc]ello 匹配所需文本,全部小写或大写首字母
      • (?=\s|\.|$) 向前看以确保字符串有一个尾随空格、. 或字符串的结尾
      • ) 展望结束
    • (?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$)) 这基本上是一样的,但对莉莲来说
    • .*?\.(?=\s|$) 捕获句子的其余部分,包括句点,并确保句点后跟空格或字符串结尾
    • )句尾捕获组1

    代码示例

    我不太了解python,所以我提供了一个PHP 示例。请注意,在 match 语句中,我使用了 s 选项,它允许 . 表达式匹配换行符

    输入文字

    Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian.
    Cello likes Lillian and kittens.
    Lillian likes Cello and dogs.  Cello has no friends. And Lillian also hasn't met anyone.
    

    代码

    <?php
    $sourcestring="your source string";
    preg_match_all('/(?:(?<=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$))(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$)).*?\.(?=\s|$))/s',$sourcestring,$matches);
    echo "<pre>".print_r($matches,true);
    ?>
    

    匹配

    $matches Array:
    (
        [0] => Array
            (
                [0] => Cello is a yellow parakeet who sings with Lillian.
                [1] =>  Cello is a yellow Lillian.
                [2] => 
    Cello likes Lillian and kittens.
                [3] => 
    Lillian likes Cello and dogs.
            )
    
        [1] => Array
            (
                [0] => Cello is a yellow parakeet who sings with Lillian.
                [1] => Cello is a yellow Lillian.
                [2] => Cello likes Lillian and kittens.
                [3] => Lillian likes Cello and dogs.
            )
    
    )
    

    如果您绝对需要匹配字符串 Cello 出现在 Lillian 之前的句子,那么您可以使用这样的表达式。在这里,我只是移动了一个右括号。

    (?:(?&lt;=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$)(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$))).*?\.(?=\s|$))

    输入文字

    Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian.
    Cello likes Lillian and kittens.
    Lillian likes Cello and dogs.  Cello has no friends. And Lillian also hasn't met anyone.
    

    捕获组 1 的输出

    [1] => Array
        (
            [0] => Cello is a yellow parakeet who sings with Lillian.
            [1] => Cello is a yellow Lillian.
            [2] => Cello likes Lillian and kittens.
        )
    

    【讨论】:

    • 它有帮助,但正则表达式会产生以下错误代码:“sre_constants.error:look-behind requires fixed-width pattern” 你是否偶然知道我该如何解决这个问题?如果您能提供任何建议,我将不胜感激。
    • 好的,这是一些语言实现正则表达式的常见问题。给我一些,我会发布更新。
    • 谢谢!如果您能帮我解决这个问题,我将不胜感激。
    • 我用\b 替换了(?&lt;=\s|^),尽管它的弹性不够好。
    • 太棒了!该脚本非常适合示例。不过,我还有最后一个问题:如果我想查找 出现在 xml 文件的同一个句子中的所有实例,你知道我如何修改表达式以找到这些实例然后打印他们要独特的路线? (如果你忙得没时间回复,我当然理解。不过,如果你能修改代码,我将永远欠你的债。)
    【解决方案2】:

    我只想围绕两个端点建立一个大型捕获组:

    import re
    
    text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."
    
    for match in re.findall(r'(Cello(?:\W{1,80}\w{1,60}){0,9}\W{0,20}Lillian)', text, flags=re.I):
        print match
    

    现在,你得到两个句子:

    Cello is a yellow parakeet who sings with Lillian
    Cello is a yellow Lillian
    

    一些提示:

    • flags=re.I 使正则表达式不区分大小写,因此 Cello 匹配 celloCello
    • (?:foo)(foo) 类似,只是捕获的文本不会显示为匹配项。这对于将事物分组而不使它们匹配很有用。

    【讨论】:

    • 谢谢!确实是一个简单的解决方案!
    猜你喜欢
    • 2012-03-20
    • 2013-11-07
    • 2021-05-30
    • 2012-03-15
    • 2023-01-10
    • 2022-07-24
    • 1970-01-01
    • 2019-07-28
    • 2018-11-11
    相关资源
    最近更新 更多