删除空格时的正则表达式匹配,如何从带有空格的原始字符串中删除匹配的字符?

时间:2013-09-13 09:17:35

标签: python regex string

(免责声明:这是我的第一个stackoverflow问题,如果我不太清楚,请提前原谅我)

预期结果:

我的任务是在表示公司名称的字符串中查找公司合法标识符,然后将它们与公司名称分开并将它们保存在单独的字符串中。 公司名称已经过清理,因此它们只包含字母数字小写字符。

示例:

company_1 = 'uber wien abcd gmbh'
company_2 = 'uber wien abcd g m b h'
company_3 = 'uber wien abcd ges mbh'

应该导致

company_1_name = 'uber wien abcd'
company_1_legal = 'gmbh'
company_2_name = 'uber wien abcd'
company_2_legal = 'gmbh'
company_3_name = 'uber wien abcd'
company_3_legal = 'gesmbh'

我现在的位置:

我从csv文件加载所有公司ID的列表。奥地利提供了一个好例子。两个法律ID是:

gmbh
gesmbh

我使用正则表达式告诉我 IF 公司名称包含合法标识符。但是,此正则表达式从字符串中删除所有空格,以便识别合法ID。

company_1_nospace = 'uberwienabcdgmbh'
company_2_nospace = 'uberwienabcdgmbh'
company_3_nospace = 'uberwienabcdgesmbh'

因为我在没有空格的字符串中查找正则表达式,所以我能够看到所有三家公司都在其名称中包含合法ID。

我被困的地方:

我可以说company_1company_2company_3中是否存在合法身份证明,但我只能将其从company_1中删除。 事实上,我无法删除g m b h,因为它不匹配,但我可以说它是合法ID。我可以删除它的唯一方法是删除公司名称的其余部分中的空格,我不想这样做(这只是最后的选择)

即使我要在gmbh中添加空格以与g m b h匹配,我也不会选择ges mbhges m b h。 (请注意,其他国家也会发生同样的事情)

我的代码:

import re
re_code = re.compile('^gmbh|gmbh$|^gesmbh|gesmbh$')
comp_id_re = re_code.search(re.sub('\s+', '', company_name))
if comp_id_re:
    company_id = comp_id_re.group()
    company_name = re.sub(re_code, '', company_name).strip()
else:
    company_id = ''

有没有办法让python 理解从原始字符串中删除哪些字符? 或者,如果以某种方式(这是另一个问题),我会找到合法身份证间距的所有可能替代方案吗?即从gmbh我创建g mbhgm bhgmb hg m bh等等,并将其用于匹配/提取?

我希望我对我的解释已经足够清楚了。考虑这个标题是相当困难的。

更新1:公司ID通常位于公司名称字符串的末尾。在某些国家,它们有时可能会处于起步阶段。

更新2:我认为这会照顾公司名称中的公司ID。它适用于公司名称末尾的法律ID,但它在开始时对公司ID不起作用

legal_regex = '^ltd|ltd$|^gmbh|gmbh$|^gesmbh|gesmbh$'
def foo(name, legal_regex):
    #compile regex that matches company ids at beginning/end of string
    re_code = re.compile(legal_regex)
    #remove spaces
    name_stream = name.replace(' ','')
    #find regex matches for legal ids
    comp_id_re = re_code.search(name_stream)
    #save company_id, remove it from string
    if comp_id_re:
        company_id = comp_id_re.group()
        name_stream = re.sub(re_code, '', name_stream).strip()
    else:
        company_id = ''
    #restore spaced string (only works if id is at the end)
    name_stream_it = iter(name_stream)
    company_name = ''.join(next(name_stream_it) if e != ' ' else ' ' for e in name)
       return (company_name, company_id)

3 个答案:

答案 0 :(得分:1)

非正则表达式解决方案在这里会更容易,这就是我要做的事情

legal_ids = """gmbh
gesmbh"""
def foo(name, legal_ids):
    #Remove all spaces from the string
    name_stream = name.replace(' ','')
    #Now iterate through the legal_ids
    for id in legal_ids:
            #Remove the legal ID's from the string
        name_stream = name_stream.replace(id, '')
    #Now Create an iterator of the modified string
    name_stream_it = iter(name_stream)
    #Fill in the missing/removed spaces
    return ''.join(next(name_stream_it) if e != ' ' else ' ' for e in name)

foo(company_1, legal_ids.splitlines())
'uber wien abcd '
foo(company_2, legal_ids.splitlines())
'uber wien abcd '
foo(company_3, legal_ids.splitlines())
'uber wien abcd '

答案 1 :(得分:0)

这是我提出的代码:

company_1 = 'uber wien abcd gmbh'
company_2 = 'uber wien abcd g m b h'
company_3 = 'uber wien abcd ges mbh'
legalids = ["gmbh", "gesmbh"]

def info(company, legalids):
    for legalid in legalids:
        found = []

        last_pos = len(company)-1
        pos = len(legalid)-1
        while True:
            if len(legalid) == len(found):
                newfound = found
                newfound.reverse()
                if legalid == ''.join(newfound):
                    return [company[:last_pos+1].strip(' '), legalid]
                else:
                    break

            if company[last_pos] == ' ':
                last_pos -= 1
                continue
            elif company[last_pos] == legalid[pos]:
                found.append(company[last_pos])
                pos -= 1
            else:
                break
            last_pos -= 1
    return

print(info(company_1, legalids))
print(info(company_2, legalids))
print(info(company_3, legalids))

输出:

['uber wien abcd', 'gmbh']
['uber wien abcd', 'gmbh']
['uber wien abcd', 'gesmbh']

答案 2 :(得分:0)

我认为我得到了一个可接受的解决方案。我使用了部分原始代码,@ Abhijit代码的一部分以及@ wei2912代码背后的主要思想。 谢谢大家

以下是我要使用的代码:

legal_ids = '^ltd|ltd$|^gmbh|gmbh$|^gesmbh|gesmbh$'

def foo(name, legal_ids):
    #initialize re (company id at beginning or end of string)
    re_code = re.compile(legal_ids)
    #remove spaces from name
    name_stream = name.replace(' ','')
    #search for matches
    comp_id_re = re_code.search(name_stream)
    if comp_id_re:
        #match was found, extract the matching company id
        company_id = comp_id_re.group()
        #remove the id from the string without spaces
        name_stream = re.sub(re_code, '', name_stream).strip()
        if comp_id_re.start()>0:
            #the legal id was NOT at the beginning of the string, proceed normally
            name_stream_it = iter(name_stream)
            final_name = ''.join(next(name_stream_it) if e != ' ' else ' ' for e in name)
        else:
            #the legal id was at the beginning of the string, so do the same as above, but with the reversed strings
            name_stream_it = iter(name_stream[::-1])
            final_name = ''.join(next(name_stream_it) if e != ' ' else ' ' for e in name[::-1])
            #reverse the string to get it back to normal
            final_name = final_name[::-1]
    else:
        company_id = ''
        final_name = name
    return (final_name.strip(), company_id)