【问题标题】:Using Regex in Python to add quantity identifier before and after Numeric Quantity value在 Python 中使用 Regex 在 Numeric Quantity 值之前和之后添加数量标识符
【发布时间】:2021-06-03 19:59:17
【问题描述】:

我在 Python 中使用 Regex 在 Numeric Quantity 值之前和之后添加数量标识符。

基本上,我必须在数字数量之后添加 QtyOrdUnits 字样,它们不在文本中。

例如:

'PartNo-001A description 20 units some other description' => 'PartNo-001A description QtyOrd 20 units some other description'
'PartNo-001A description QtyOrd 20 some other description' => 'PartNo-001A description QtyOrd 20 units some other description'
'PartNo-001A description QtyOrd 20' => 'PartNo-001A description QtyOrd 20 units'
'PartNo-001A QtyOrd 20' => 'PartNo-001A QtyOrd 20 units'
'PartNo-001A 20 units'=> 'PartNo-001A QtyOrd 20 units'

正在使用的代码如下:

import re

def process_QtyOrd( text):
    for x in re.findall("(qtyord [0-9]+ units| [0-9]+ units|qtyord [0-9]+|qtyord[0-9]+units )", text.lower()):
        Text_Intermediate = "OrderQty " + str(re.search("[0-9]+", x).group()) + " Units"
    
    Text_Final = re.sub("(qtyord [0-9]+ units|[0-9]+ units|qtyord [0-9]+|qtyord [0-9]+ units)", Text_Intermediate, text, flags= re.IGNORECASE)

    return Text_Final

text1 = 'PartNo-001A description 20 units some other description'
text2 = '''
Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

QtyOrd 20 units some other description

''' 
text3 = 'PartNo-001A description QtyOrd 20 some other description'
text4 = 'PartNo-001A description QtyOrd 20'
text5 = 'PartNo-001A QtyOrd 20'
text6 = 'PartNo-001A 20 units'
text7 = ''' 

Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

QtyOrd 20 units some other description PartNo-001A
 
''' 

text8 = ''' 

Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

PartNo-001A

QtyOrd 
20

''' 

然后:

print(process_QtyOrd(text1))
print(process_QtyOrd(text2))
print(process_QtyOrd(text3))
print(process_QtyOrd(text4))
print(process_QtyOrd(text5))
print(process_QtyOrd(text6))
print(process_QtyOrd(text7))
print(process_QtyOrd(text8))

对于text8,代码不起作用。 你能帮我解决这个问题吗?

输出应该是这样的:

1. PartNo-001A description QtyOrd 20 Units some other description
 

2. Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

QtyOrd 20 Units some other description


3. PartNo-001A description QtyOrd 20 Units some other description
4. PartNo-001A description QtyOrd 20 Units
5. PartNo-001A QtyOrd 20 Units
6. PartNo-001A QtyOrd 20 Units
 

7. Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

QtyOrd 20 Units some other description PartNo-001A
 

8. Could you please redirect the ticket to the correct sales department so they can provide assistance and a quote for the items
below.

PartNo-001A

QtyOrd 
20
units

【问题讨论】:

    标签: python regex regex-lookarounds regex-group re


    【解决方案1】:

    你可以使用

    import re
    text = r'PartNo-001A description 20 units some other description'
    pattern = re.compile(r'\b(?:qtyord\s*(\d+)(?:\s*units)?|(\d+)\s*units)\b', re.I)
    Text_Final = pattern.sub(r'QtyOrd \1\2 units', text)
    print(Text_Final)
    # => PartNo-001A description QtyOrd 20 units some other description
    

    请参阅regex demothe Python demo

    详情

    • \b - 字边界
    • (?: - 非捕获组的开始
      • qtyord
      • \s* - 零个或多个空格
      • (\d+) - 第 1 组(在替换模式中用 \1 表示):一位或多位数字
      • (?:\s*units)? - 匹配零个或多个空格和 units 单词的可选组(如果您还想以单数形式匹配 unit,请在 s 之后添加 ?
    • | - 或
      • (\d+) - 第 2 组(在替换模式中用 \2 表示):一位或多位数字
      • \s*units - 零个或多个空格和 units 单词(如果您还想匹配 unit 的单数,请在 s 之后添加 ?
    • ) - 小组结束
    • \b - 字边界

    【讨论】:

    • 代码运行良好。仅对于其他数字,它也添加到 QtyOrd 和 Unit。为了。例如。 'PartNo-001A 描述 20 个单位其他 3 毫米描述' => 'PartNo-001A 描述 QtyOrd 20 个单位一些其他 QtyOrd 3 单位毫米描述'。 QtyOrd 和 Unit 只能用于数字数量,不能用于任何其他数值。输入文本可能包含大量数值。但它只会添加数量
    • @SafayetKarim 抱歉,第二种选择不需要可选组。我已经更新了代码和演示。
    【解决方案2】:

    假设您对 text8 的预期结果是 OrderQty 20 Units, 不是QtyOrd 20 units,请你试试:

    def process_QtyOrd(text):
        m = re.match(r'^(.*?)(qtyord\s*\d+\s*units|\d+\s+units|qtyord\s+\d+)(.*)$', text, flags=re.IGNORECASE|re.DOTALL)
        if m:
            str= re.sub(r'\D*(\d+)\D*', r'OrderQty \1 Units', m.group(2))
            text = m.group(1) + str + m.group(3)
        return text
    
    • re.match 将输入 text 分解为三个子字符串: 我们要修改的感兴趣的部分,前导子字符串,以及 尾随子字符串。
    • 我使用\s 而不是 (空格)来匹配换行符。
    • 感兴趣的部分由m.groups(2) 捕获。然后我们可以 用re.sub()函数修改它。
    • 最后的text 是上述子字符串的串联。

    [更新]

    请您尝试以下方法:

    def process_QtyOrd(text):
        text = re.sub(r'(qtyord\s*\d+\s*units|\d+\s+units|qtyord\s+\d+)', lambda m: re.sub(r'\D*(\d+)\D*', r'QtyOrd \1 Units', m.group(1)), text, flags=re.IGNORECASE|re.DOTALL)
        return text
    

    现在,如果文本包含多个模式,它将起作用。我已将替换文本中的单词 OrderQty 更改为 QtyOrd

    • 我使用的不是上一个答案中的re.match() 函数 re.sub() 函数一次替换文本中所有出现的模式。
    • 引入了 lambda 函数来评估替换部件作为 表达。

    [更新2]

    如果您想包含十进制数字,请尝试以下操作:

    def process_QtyOrd(text):
        text = re.sub(r'(qtyord\s*\d+(?:\.\d+)?\s*units|\d+(?:\.\d+)?\s+units|qtyord\s+\d+(?:\.\d+)?)', lambda m: re.sub(r'\D*(\d+(?:\.\d+)?)\D*', r'QtyOrd \1 Units', m.group(1)), text, flags=re.IGNORECASE|re.DOTALL)
        return text
    

    概念是将\d+ 替换为\d+(?:\.\d+)?,它匹配数字后跟可选的点和数字。

    【讨论】:

    • 对于 text8 应该是 QtyOrd 20 个单位,而不是 OrderQty 20 个单位
    • 您的预期结果显示从 text1 到 text7 的“OrderQty 20 Units”,而只有 text8 包含“QtyOrd 20 units”。产生差异的规则是什么?
    • 对不起。我想我写错了输出。我需要在数量之前和之后的所有文本都应该是 QtyOrd 和 Unit。
    • 我已经检查了一行代码工作正常。但是,如果我想更改多行,那么它仅适用于第一行。请参阅下面的示例输入文本: text1 =''' ITEM NO. 1 数量 2 UOM EA 制造商 NOV 制造商 PartNoId PartNo-001A PartNoId 名称 联轴器描述 绞车润滑油泵的联轴器轮毂 项目编号1 数量 2 UOM EA 制造商 NOV 制造商 PartNoId PartNo-001A PartNoId 名称 联轴器描述 绞车润滑油泵的联轴器轮毂 ''' '''
    • 感谢您的反馈。现在很清楚了。请给我一点时间来更新我的代码。
    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 2022-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多