我有一个 Python 脚本,我们用它来解析 CSV 文件,其中包含用户输入的电话号码 - 因此,有很多奇怪的格式/错误。我们需要将这些数字解析为单独的组件,并修复一些常见的输入错误。
我们的电话号码适用于悉尼或墨尔本(澳大利亚)或奥克兰(新西兰),以国际格式提供。
我们的标准悉尼号码如下所示:
+61(2)8328-1972
我们有国际前缀+61
,后跟括号中的一位数字区号,2
,后跟本地组件的两半,用连字符分隔,8328-1972
。
墨尔本号码在区号中只有 3 而不是 2,例如
+61(3)8328-1972
奥克兰号码相似,但它们有一个 7 位数的本地组件(3 个然后 4 个号码),而不是正常的 8 位数。
+64(9)842-1000
我们也有一些常见错误的匹配项。我已经将正则表达式分离到它们自己的类中。
class PhoneNumberFormats():
"""Provides compiled regex objects for different phone number formats. We put these in their own class for performance reasons - there's no point recompiling the same pattern for each Employee"""
standard_format = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<area_code>\d)\)(?P<local_first_half>\d{3,4})-(?P<local_second_half>\d{4})')
extra_zero = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{3,4})-(?P<local_second_half>\d{4})')
missing_hyphen = re.compile(r'^\+(?P<intl_prefix>\d{2})\(0(?P<area_code>\d)\)(?P<local_first_half>\d{3,4})(?P<local_second_half>\d{4})')
space_instead_of_hyphen = re.compile(r'^\+(?P<intl_prefix>\d{2})\((?P<area_code>\d)\)(?P<local_first_half>\d{3,4}) (?P<local_second_half>\d{4})')
我们有一个用于standard_format 数字,然后其他用于各种常见错误情况,例如在区号之前添加一个额外的零(02
而不是2), or missing hyphens in the local component (e.g.
83281972 instead of
8328-1972`)等。
然后我们从级联的 if/elifs 中调用它们:
def clean_phone_number(self):
"""Perform some rudimentary checks and corrections, to make sure numbers are in the right format.
Numbers should be in the form 0XYYYYYYYY, where X is the area code, and Y is the local number."""
if not self.telephoneNumber:
self.PHFull = ''
self.PHFull_message = 'Missing phone number.'
else:
if PhoneNumberFormats.standard_format.search(self.telephoneNumber):
result = PhoneNumberFormats.standard_format.search(self.telephoneNumber)
self.PHFull = '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half')
self.PHFull_message = ''
elif PhoneNumberFormats.extra_zero.search(self.telephoneNumber):
result = PhoneNumberFormats.extra_zero.search(self.telephoneNumber)
self.PHFull = '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half')
self.PHFull_message = 'Extra zero in area code - ask user to remediate.'
elif PhoneNumberFormats.missing_hyphen.search(self.telephoneNumber):
result = PhoneNumberFormats.missing_hyphen.search(self.telephoneNumber)
self.PHFull = '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half')
self.PHFull_message = 'Missing hyphen in local component - ask user to remediate.'
elif PhoneNumberFormats.space_instead_of_hyphen.search(self.telephoneNumber):
result = PhoneNumberFormats.missing_hyphen.search(self.telephoneNumber)
self.PHFull = '0' + result.group('area_code') + result.group('local_first_half') + result.group('local_second_half')
self.PHFull_message = 'Space instead of hyphen in local component - ask user to remediate.'
else:
self.PHFull = ''
self.PHFull_message = 'Number didn\'t match recognised format. Original text is: ' + self.telephoneNumber
我的目标是使匹配尽可能紧密,但至少仍能捕捉到常见错误。
不过,我在上面所做的事情有很多问题:
- 我
\d{3,4}
用来匹配本地组件的前半部分。然而,理想情况下,如果它是新西兰号码(即以 开头) ,我们真的只想捕捉前半部分的 3 位数+64(9)
。这样,我们可以标记缺少数字的悉尼/墨尔本号码。我可以将 auckland_number 分离成它自己的正则表达式模式PhoneNumberFormats
,但是,这意味着它不会捕获结合错误情况(extra_zero、missing_hyphen、space_instead_of_hyphen)的新西兰数字。因此,除非我仅为奥克兰重新创建它们的版本,例如 auckland_extra_zero,这似乎毫无意义地重复,否则我看不出如何轻松解决这个问题。 - 我们不会拾取错误的组合——例如,如果它们有一个额外的零和一个缺失的连字符,我们将不会拾取它。有没有一种简单的方法可以使用正则表达式来做到这一点,而无需明确创建不同错误的排列?
我想解决以上两个问题,并希望稍微收紧一点,以抓住我错过的任何东西。有没有更聪明的方法来做我上面试图做的事情?
干杯,维克多
补充评论:
以下只是提供一些上下文:
此脚本适用于一家全球性公司,在悉尼设有办事处,在墨尔本设有办事处,在奥克兰设有办事处。
这些数字来自员工的内部活动目录列表(即,它不是客户列表,而是我们自己的办公电话)。
因此,我们不是在寻找通用的澳大利亚电话号码匹配脚本,而是在寻找用于解析来自三个特定办公室的号码的通用脚本。一般来说,只有最后 4 个数字应该不同。
不需要手机。
该脚本旨在解析 Active Directory 的 CSV 转储,并将数字重新格式化为另一个程序可接受的格式 (QuickComm)
该程序来自外部供应商,并且需要我在上面的代码中生成的确切格式的数字 - 这就是为什么数字像 0283433422 一样被吐出。
我编写的脚本无法更改记录,它仅适用于它们的 CSV 转储 - 记录存储在 Active Directory 中,访问它们以修复它们的唯一方法是向员工发送电子邮件并询问他们登录并更改自己的记录。
所以这个脚本由一个 PA 运行,以产生这个程序所需的输出。她/他还将获得一份数字格式错误的人员列表 - 因此会收到有关要求用户进行补救的消息。理论上,这些应该只有少数。然后我们给这些员工发电子邮件/打电话,要求他们修复他们的记录 - 脚本每月运行一次(数字可能会改变),我们还需要标记那些设法输入错误记录的新员工。
@John Macklin:您是否建议我废弃正则表达式,然后尝试从字符串中提取特定位置的数字?
我一直在寻找一种方法来捕捉常见的错误情况,组合(例如空格而不是连字符,再加上一个额外的零),但这不是很容易实现吗?