【问题标题】:regex substitute every appearance of a capture group with another capture group正则表达式用另一个捕获组替换捕获组的每个外观
【发布时间】:2021-04-25 05:32:29
【问题描述】:

我正在重新格式化大量销售数据。

每次销售都会显示商品名称、所售商品数量以及四舍五入到最接近整数的价格。

1 袋 20 个苹果售价 3 美元: Apple/,20,3,

如果发生多次销售,销售数据将替换第一个结果之后的每个结果的项目名称。

4 袋 20 个苹果售价 3 美元: Apple/,20,3%20,3%20,3%20,3,

我需要显示每次销售的商品名称,而不是 % 符号

想要的结果Apple/,20,3,Apple/,20,3,Apple/,20,3,Apple/,20,3,

到目前为止: 我已经为此努力了六个小时,并尝试了几种方法。

我曾想过在 python 中使用表达式 ([A-Za-z]+\/)?(\%)?(\d+\,\d+\,) 运行正则表达式替换 将\1\3 替换为完整匹配后会产生所需的结果,但是这只会将第一个捕获组应用于第三个捕获组的所有连续匹配的开头。

Apple/,20,3,20,3,20,3,20,3,

我怀疑这与捕获组和捕获对象之间的差异有关,但我一直在尝试找到一种方法将第一个捕获组附加到给定捕获组的捕获对象的每个外观(例如,追加捕获第 1 组到捕获第 3 组的每场比赛的开始。)

为了解决这个问题,我尝试了答案的修改版本:https://stackoverflow.com/questions/32670413/replace-all-matches-using-re-findall

import re

regex = re.compile('([A-Za-z]+\/)?(\%)?(\d+\,\d+\,)', re.S)
itemsales =  'Apple/20,3,%20,3,%20,3,%20,3,'
sales_fixed = regex.sub(lambda m: m.group().replace('%',"\1",1), myfile)
print(sales_fixed)

这将返回完全相同的结果

Apple/,20,3,20,3,20,3,20,3,

我怀疑这可能是由于在替换中错误地引用了我的捕获组

如何用产品名称替换百分号?

【问题讨论】:

    标签: python regex


    【解决方案1】:

    你尝试的模式只匹配最后一部分,因为前两部分是可选的,它可以匹配%20,3,部分

    匹配问题中描述的格式,您可以在第 1 组中首先匹配 Apple/ 之后重复匹配数字逗号数字后跟 % 的部分。

    然后在替换中,在 2 个逗号的 x.group(1) 之间使用捕获组 1

    关于代码和模式的几点说明:

    • 您不必使用re.S,因为模式中没有必须匹配换行符的点。
    • 您不必逃避, /%
    • 在问题描述和示例代码中使用了 2 个不同的字符串。

    模式可能如下所示:

    \b([A-Za-z]+/),(?:\d+,\d+%)+
    
    • \b防止部分匹配的单词边界
    • ( 捕获第 1 组
      • [A-Za-z]+/ 在 A-Z a-z 范围内匹配一个字符 1+ 次
    • )关闭第一组
    • ,(?:\d+,\d+%)+ 匹配一个逗号,重复 1+ 次匹配 1+ 个数字,一个逗号再匹配 1+ 个数字

    例如

    import re
    
    pattern = r"\b([A-Za-z]+/),(?:\d+,\d+%)+"
    itemsales = "Apple/,20,3%20,3%20,3%20,3,"
    
    sales_fixed = re.sub(
        pattern,
        lambda x: x.group().replace('%', ",{0},".format(x.group(1))),
        itemsales
    )
    
    print(sales_fixed)
    

    输出

    Apple/,20,3,Apple/,20,3,Apple/,20,3,Apple/,20,3,
    

    Regex demo | Python demo

    【讨论】:

      【解决方案2】:

      让我们修复您的代码

      regex = re.compile(r'\b([A-Za-z]+/)\S+', re.S)
      sales_fixed = regex.sub(lambda m: m.group().replace('%', f',{m.group(1)},'), itemsales)
      

      >>> sales_fixed
      
      Apple/,20,3,Apple/,20,3,Apple/,20,3,Apple/,20,3,
      

      正则表达式详细信息:

      • \b : 在单词边界断言位置
      • ([A-Za-z]+/) : 第一个捕获组
        • [A-Za-z]+ :匹配列表中的任意字符一次或多次
        • / :匹配字符 / 字面意思
      • \S+ :匹配任何非空白字符一次或多次

      【讨论】:

        【解决方案3】:

        使用您展示的示例,请尝试在 Python3.6 中进行以下、编写和测试。简单的解释是:创建一个名为s 的变量,其中包含OP 显示的所有值,然后在此处使用python 库re。在这里使用re.sub进行替换;创建具有获取值的捕获组的值的 var,最后执行替换 实际变量 s。

        import re
        s="Apple/,20,3%20,3%20,3%20,3,"
        var=re.sub('^([A-Za-z]+/).*', r"\1", s, flags=re.MULTILINE)
        re.sub('%(\d+)', r','+var+',\g<1>', s, flags=re.MULTILINE)
        'Apple/,20,3,Apple/,20,3,Apple/,20,3,Apple/,20,3,'
        

        【讨论】:

          猜你喜欢
          • 2012-03-01
          • 1970-01-01
          • 2014-06-19
          • 2010-11-19
          • 1970-01-01
          • 2021-11-10
          • 1970-01-01
          • 2015-07-24
          • 2019-02-22
          相关资源
          最近更新 更多