【问题标题】:Find numbers in a string and decrement them在字符串中查找数字并递减它们
【发布时间】:2015-06-12 14:59:00
【问题描述】:

我有一个 HTML 页面,其中列出了很长的主题索引和页码。我想查找所有页码及其锚标记链接,并将页码减少1

这是 HTML 中的示例行:

<p class="index">breakeven volume (BEV), <a href="ch02.xhtml#page28">28</a></p>

我正在尝试在这两个地方找到数字28,并减少1

到目前为止,我已经能够找到该数字并将其替换为自身,但我不知道如何减少它。到目前为止我的代码:

import fileinput
import re

for line in fileinput.input():
    line = re.sub(r'\>([0-9]+)\<', r'>\1<', line.rstrip())
    print(line)

【问题讨论】:

    标签: python replace decrement


    【解决方案1】:

    您可以在替换时使用替换函数:

    import re
    s = '<p class="index">breakeven volume (BEV), <a href="ch02.xhtml#page28">28</a></p>'
    re.sub(r'page(\d+)">\1', lambda m: 'page{0}">{0}'.format(int(m.group(1)) - 1), s)
    

    结果:

    <p class="index">breakeven volume (BEV), <a href="ch02.xhtml#page27">27</a></p>
    

    page(\d+)"&gt;\1 我们匹配 page 后跟一个数字,然后是一个 ">,然后是与第一对括号中的模式中相同的数字(\1)。

    替换函数将匹配作为参数。所以我们取匹配的第一组(m.group(1)),也就是数字,我们解析它并递减它。然后我们使用递减的数字重构新的字符串。

    【讨论】:

    • 提供更多解释可能会很好,而不是内联所有内容并让 OP 遍历它...也就是说,我喜欢替换这两个值的多合一方法.
    • 感谢@jonrsharpe 的反馈
    • 谢谢你,我永远无法自己解决这个问题!我能够将您的代码合并到我的代码中,让它逐行解析 xml 并将其作为新文件吐出。
    • @JohnGayle 它应该适用于整个 xml,而不是逐行......如果不是,它可能需要调整
    • @JuniorCompressor 这是我最终得到的代码p = re.sub(r'page(\d+)"&gt;\1', lambda m: 'page{0}"&gt;{0}'.format(int(m.group(1)) - 1), line.rstrip()) 然后我将结果写入文本文件。
    【解决方案2】:

    请注意,您可以将 函数 作为 repl 参数传递给 re.sub,对于每个不重叠的 @ 987654326@":

    def decrement(match):
        """Decrement the number in the match."""
        return str(int(match.group()) - 1)
    

    请注意,这期望match.group() 代表一个整数;要仅捕获数字,而不包括 &gt;&lt;,请使用环视(参见 demo):

    page_num = re.compile(r'''
        (?<=>) # a > before the group
        \d+    # followed by one or more digits
        (?=<)  # and a < after the group
    ''', re.VERBOSE)
    

    这可以按您的要求工作:

    >>> page_num.sub(decrement, line)
    '<p class="index">breakeven volume (BEV), <a href="ch02.xhtml#page28">27</a></p>'
    

    并且可以类似地应用于'#page28"'

    但是,请注意,您通常应该使用真正的 HTML 解析器,而不是正则表达式来解析 HTML(不是常规语言)。

    【讨论】:

    • step= 参数是无用的,因为绝对没有办法提供它。如果你真的想要它,你可以这样做:def decrementer(step=1): return lambda match: str(int(match.group()) - step) 然后page_num.sub(decrementer(), line)page_num.sub(decrementer(2), line)
    • @Matt 有两种方法可以提供它:使用 functools.partiallambda。话虽如此,我认为您的方法(除了lambda 用法)更整洁。
    • 此时将整个函数内联为 lambda 会更容易。或者你可以像我一样做。
    • 顺便说一句,我希望我能给你第二个+1,因为我提到 HTML 不是常规语言。尽管在这种情况下,OP 似乎拥有有限的数据集,其中正则表达式可以更快地完成工作,而无需解决一般情况下的问题。
    • @Matt 我认为这通常是人们最终使用正则表达式解析 HTML 的原因——对于他们开始的有限集合来说,这似乎更简单,但不可避免地会出现边缘情况,表达式变得更复杂,然后他们会可能最好还是硬着头皮开始正确解析!
    猜你喜欢
    • 1970-01-01
    • 2014-01-15
    • 2014-08-11
    • 1970-01-01
    • 2016-01-20
    • 2023-03-20
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多