【问题标题】:replace some part of a word with regex用正则表达式替换单词的某些部分
【发布时间】:2010-11-10 21:57:40
【问题描述】:

如何删除<ref> *some text*</ref> 中的文本以及ref 本身?

'...and so on<ref>Oxford University Press</ref>.'

re.sub(r'<ref>.+</ref>', '', string) 仅删除 <ref> 如果 <ref> 后跟一个空格

编辑:我猜它与单词边界有关......或者?

EDIT2 我需要的是它会计算最后一个(关闭)</ref>,即使它在换行符上。

【问题讨论】:

    标签: python replace ref


    【解决方案1】:

    我真的不认为你有问题,因为粘贴的代码将删除字符串的<ref>...</ref> 部分。但是,如果您的意思是,并且没有删除空的 ref 标记:

    re.sub(r'<ref>.+</ref>', '', '...and so on<ref></ref>.')
    

    那么你需要做的就是把 .+ 换成 .*

    A + 表示一个或多个,而 * 表示零或多个。

    来自http://docs.python.org/library/re.html

    '.' (Dot.) In the default mode, this matches any character except a newline.
        If the DOTALL flag has been specified, this matches any character including
        a newline.
    '*' Causes the resulting RE to match 0 or more repetitions of the preceding
        RE, as many repetitions as are possible. ab* will match ‘a’, ‘ab’, or ‘a’
        followed by any number of ‘b’s.
    '+' Causes the resulting RE to match 1 or more repetitions of the preceding
        RE. ab+ will match ‘a’ followed by any non-zero number of ‘b’s; it will
        not match just ‘a’.
    '?' Causes the resulting RE to match 0 or 1 repetitions of the preceding RE.
        ab? will match either ‘a’ or ‘ab’.
    

    【讨论】:

    • 如果关闭 &lt;/ref&gt; 在换行符上怎么办?我该如何处理?
    • 显然有一个标志 (re.DOTALL) 使得 '.'匹配所有字符包括换行符。但这似乎不适用于我在 python2.6 中的 re 模块。 更新:查看 docs.python.org/library/re.html 它说 re.sub:在 2.7、3.1 版中更改:添加了可选的标志参数。
    • 我已经尝试过(re.DOTALL)re.sub(r'(?s)&lt;ref&gt;.*&lt;/ref&gt;',但它失去了控制并且删除了太多,超过一半的文本 - 这绝对是错误的。还有其他想法吗?
    • 再次来自docs.python.org/library/re.html:“''、'+' 和 '?'限定词都是贪婪的”。这意味着它将匹配第一个 和 _last_ 。您可以通过添加 ?到 * (re.sub(r'(?s).?')。试试看
    • 看起来(re.sub(r'(?s)&lt;ref&gt;.*?&lt;/ref&gt;') 使用re.DOTAL 和r'&lt;ref&gt;[^&lt;]*&lt;/ref&gt;' 使用@erkmene 的[^&lt;] 是一回事
    【解决方案2】:

    你可以制作一个花哨的正则表达式来做你想做的事,但是你需要使用 DOTALL 和非贪婪搜索,并且你需要了解正则表达式的一般工作原理,而你不需要。

    你最好的选择是使用字符串方法而不是正则表达式,这更 Pythonic:

    while '<reg>' in string:
        begin, end = string.split('<reg>', 1)
        trash, end = end.split('</reg>', 1)
        string = begin + end
    

    如果您想要非常通用,允许标签或空格和标签中的属性奇怪的大写,您也不应该这样做,而是投资学习 html/xml 解析库。 lxml 目前似乎被广泛推荐并得到很好的支持。

    【讨论】:

      【解决方案3】:

      您可能要小心,不要仅仅因为有多个结束 &lt;/ref&gt;s 就删除大量文本。在我看来,下面的正则表达式会更准确:

      r'<ref>[^<]*</ref>'
      

      这将阻止“贪婪”匹配。

      顺便说一句:有一个很棒的工具叫做 The Regex Coach 来分析和测试你的正则表达式。您可以在以下位置找到它:http://www.weitz.de/regex-coach/

      编辑:忘记在第一段添加代码标签。

      【讨论】:

        【解决方案4】:

        如果您尝试使用正则表达式执行此操作,您将获得world of trouble。您正在有效地尝试解析某些内容,但您的解析器无法胜任这项任务。

        贪婪地跨字符串匹配可能会消耗太多,如下例所示:

        <ref>SDD</ref>...<ref>XX</ref>
        

        你最终会清理整个中间。

        你真的想要一个解析器,比如Beautiful Soup

        from BeautifulSoup import BeautifulSoup, Tag
        s = "<a>sfsdf</a> <ref>XX</ref> || <ref>YY</ref>"
        soup = BeautifulSoup(s)
        x = soup.findAll("ref")
        for z in x:
          soup.ref.replaceWith('!')
        soup # <a>sfsdf</a> ! || !
        

        【讨论】:

        • 我知道远离正则表达式清理 html 会更实用,但仍然......为了练习,我必须使用它。
        • 虽然这几乎总是正确的方法,特别是如果您正在刮擦;以我的经验,它为小型查找和替换脚本引入了不必要的复杂性。如果仔细测试,我上面描述的正则表达式方法可以快速解决大部分问题。
        猜你喜欢
        • 2015-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-16
        • 2022-12-10
        • 1970-01-01
        相关资源
        最近更新 更多