Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 正则表达式用另一个捕获组替换捕获组的每个外观_Python_Regex - Fatal编程技术网

Python 正则表达式用另一个捕获组替换捕获组的每个外观

Python 正则表达式用另一个捕获组替换捕获组的每个外观,python,regex,Python,Regex,我正在重新格式化一大组销售数据 每次销售都会显示商品名称、销售商品数量以及四舍五入至最接近整数的价格 1袋20个苹果售价3美元: Apple/,20,3, 如果发生多个销售,则销售数据将替换第一个销售结果之后每个结果的项目名称 4袋20个苹果售价3美元:Apple/,20,3%20,3%20,3, 我需要显示每次销售的商品名称,而不是%符号 期望结果:苹果/,20,3,苹果/,20,3,苹果/,20,3,苹果/,20,3,苹果/,20,3, 到目前为止: 我已经用头撞了六个小时,并尝试了几种方法

我正在重新格式化一大组销售数据

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

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

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

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

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

期望结果
苹果/,20,3,苹果/,20,3,苹果/,20,3,苹果/,20,3,苹果/,20,3,

到目前为止: 我已经用头撞了六个小时,并尝试了几种方法

我曾想过在python中使用re模块运行正则表达式替换,使用表达式
([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,
我怀疑这可能是因为在替换中错误引用了我的捕获组

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

让我们修复您的代码

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)

正则表达式详细信息:

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

对于您展示的样本,请尝试使用Python3.6编写并测试以下内容。简单的解释是:创建一个名为
s
的变量,其中包含OP显示的所有值,然后在此使用python的
re
库。使用
re.sub
在此处执行替换;创建var,该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,'
重新导入
s=“苹果/,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',s,flags=re.MULTILINE)
“苹果/,20,3,苹果/,20,3,苹果/,20,3,苹果/,20,3,”

您尝试的模式仅与最后一部分匹配,因为前两部分是可选的,并且它可以与
%
20,3,
部分匹配

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

然后在替换中,在两个逗号之间使用捕获组1。组(1)

关于代码和模式的一些注释:

  • 您不必使用
    re.S
    ,因为图案中没有必须与换行符匹配的点
  • 您不必逃避
    /
    %
  • 在问题描述和示例代码中使用了两个不同的字符串
该模式可能看起来像:

\b([A-Za-z]+/),(?:\d+,\d+%)+
  • \b
    防止部分匹配的单词边界
  • Capturegroup 1
    • [A-Za-z]+/
      匹配A-z A-z范围内字符的1+倍
  • 关闭第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,
|

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