首页 > 解决方案 > “管道”正则表达式操作

问题描述

在将它们传递给模型之前,我正在尝试使用大量正则表达式操作来清理一些字符串。以前,我在数据帧级别上工作,我可以使用 pandas 的apply函数来伪管道我的正则表达式操作:

# take out website prefixes (e.g. www) and suffixes (e.g. .com, .de, .it)
test['shopname'] = test.shopname.apply(lambda x: x if re.match(r'(.*(?<!-))(www)\.(.*)',x) is None else re.match(r'(.*(?<!-))(www)\.(.*)',x).group(3).strip()).apply(lambda x: x if re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$',x) is None else re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$',x).group(1).strip()) 

apply但是,现在我正在尝试编写一个可以用ie调用的行级函数

test['identified_name'] = test.apply(lambda row: shop_name_cleaning(row['shopname']), axis=1)

我不知道如何为后续的正则表达式操作“管道”我的字符串了。我的主要斗争是让代码在模式不匹配时返回原始字符串,以便将其传递给下一个正则表达式操作。

我试过:

def shop_name_cleaning(shop_name):
        clean_name = str(re.sub(r'(.*(?<!-))(www)\.(.*)',x), r'\3', trunc_de043)).str(re.sub(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', r'\1', trunc_de043))

return clean_name

但 Python 说:

AttributeError: 'str' object has no attribute 'str'

我也试过:

def shop_name_cleaning(shop_name):
        clean_name = str(re.match(r'(.*(?<!-))(www)\.(.*)', trunc_de043).group(3).strip() or trunc_de043).str(re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', trunc_de043).group(1).strip() or trunc_de043)

return clean_name

or不起作用。

我至少有 10 个正则表达式操作。我正在寻找一种不需要我编写大量if/else语句的解决方案(因为如果不匹配,我希望返回原始字符串)。

标签: pythonregex

解决方案


您的实际错误来自因为您有str(..).str(...)并且没有"someting".str(...)功能。

match但是,您忽略了可以返回的事实None。你必须检查match实际返回的东西,如果没有返回原件

def shop_name_cleaning(shop_name):
    match = re.match(r'(.*(?<!-))(www)\.(.*)', shop_name)
    shop_name = match.group(3).strip() if match else shop_name

    match = re.match(r'(.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$', shop_name)
    shop_name = match.group(1).strip() if match else shop_name

    return shop_name

如果你有太多的正则表达式,你可以创建一个辅助函数并做一个 reduce - 但你必须确保所有结果组都可以以相同的方式添加,例如通过命名它们:

from functools import reduce

def clean_name(name, regex):
    match = re.match(regex, name)
    return match.group("out").strip() if match else name
    
    # Or in 3.8+
    return match.group("out").strip() if match:=re.match(regex, name) else name


regexes = [
    r'(.*(?<!-))(www)\.(?P<out>.*)',
    r'(?P<out>.*)\.(?=\bcom\b|\bde\b|\bit\b|\bco\.uk\b|\beu\b|\blv\b).*$',
]

reduce(clean_name, regexes, shop_name)

推荐阅读