使用regex、java从电话号码中删除可选零
我有一个java类(称为使用regex、java从电话号码中删除可选零,java,android,regex,phone-number,Java,Android,Regex,Phone Number,我有一个java类(称为PhoneNumber)来验证和处理电话号码 我自己编写了最后一个方法(删除可选零),但我希望它更简单一点(可能使用正则表达式识别可选零,并使用相同的正则表达式删除它,就像optional\u PHONE\u NUMBER\u CHARACTERSpart)。这段代码感觉很脆弱,不是100%正确,尽管我认为它满足了我的需要,涵盖了我能想到的所有单元测试 谁能给我一个明确的例子,包括一个适当的正则表达式?(也欢迎其他简单的解决方案) 如您所见,我提取了用于删除可选字符的代码
PhoneNumber
)来验证和处理电话号码
我自己编写了最后一个方法(删除可选零),但我希望它更简单一点(可能使用正则表达式识别可选零,并使用相同的正则表达式删除它,就像optional\u PHONE\u NUMBER\u CHARACTERS
part)。这段代码感觉很脆弱,不是100%正确,尽管我认为它满足了我的需要,涵盖了我能想到的所有单元测试
谁能给我一个明确的例子,包括一个适当的正则表达式?(也欢迎其他简单的解决方案)
如您所见,我提取了用于删除可选字符的代码,以防我需要使用电话号码拨打电话。例如,+3112-3456-789
将变成+31123456789
我希望使用方法removeOptionalCharacters
进行的转换如下:
+31 (0)12 3456 789 > +31123456789
+31 (012) 3456 789 > +31123456789
(0)12 3456 789 > 0123456789
(012) 3456 789 > 0123456789
总结一下,以下是应该成功的单元测试:
@Test
public void removeOptionalCharacters_HooksAroundOptionalZero_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+31 (0)12 3456789");
assertEquals("+31123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCode_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+31 (012) 3456789");
assertEquals("+31123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundOptionalZeroWithoutCountryCode_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(0)12 3456789");
assertEquals("0123456789", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeWithoutCountryCode_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(012)3456789");
assertEquals("0123456789", compactPhoneNumber);
}
我认为这些测试覆盖了所有带有可选零的常见情况。当然,还有更多的单元测试来涵盖整个内容(3456789部分还可以包括不应删除的零,以及其他可选字符,如-和+也不应受到影响等),但为了简单起见,我将它们省略了。如果你想一想电话号码,你就可以自己猜剩下的。不过你可以试试这个
([+]*)([ ])*(\w)?([\d]+)
我可以试试这个
([+]*)([ ])*(\w)?([\d]+)
我将使用两个正则表达式。一个用于验证电话号码,另一个用于规范化电话号码,省去可选字符。 您的规范化正则表达式应该包含独占匹配组(由|分隔)。(0)的匹配组将是
(\(0\))
我确信有Java API可用于访问各个匹配组,并用您喜欢的任何内容替换它们
组合(0)和其他字符的正则表达式为:
(\(0\))|([\\s()/.-])
仅将第一个匹配组的第一个匹配项替换为“”。
将第二组的所有匹配项替换为“”
或者让代码保持原样。它是自文档化的可读代码。正则表达式需要文档。我将使用两个正则表达式。一个用于验证电话号码,另一个用于规范化电话号码,省去可选字符。 您的规范化正则表达式应该包含独占匹配组(由|分隔)。(0)的匹配组将是
(\(0\))
我确信有Java API可用于访问各个匹配组,并用您喜欢的任何内容替换它们
组合(0)和其他字符的正则表达式为:
(\(0\))|([\\s()/.-])
仅将第一个匹配组的第一个匹配项替换为“”。
将第二组的所有匹配项替换为“”
或者让代码保持原样。它是自文档化的可读代码。正则表达式需要文档。休息一晚后,我想出了一个问题中提供的示例的简单版本:拆分正则表达式可以用于替换,甚至更好,因为它还可以替换(012)区号的可选0(最后一个钩子仍将替换为所有其他可选字符) 除此之外,我的示例代码还删除了电话号码中所有额外的零(我认为这是Anubhava在评论中的部分意思)。我的新解决方案也解决了这一问题:
private static final String OPTIONAL_ZERO_REGEX = Pattern.quote("(0");
public static String removeOptionalZero(String phoneNumber)
{
String[] split = phoneNumber.split(OPTIONAL_ZERO_REGEX);
if (split.length == 2 && !split[0].isEmpty())
{ // Only remove the optional zero when preceded by a country code
return phoneNumber.replaceFirst(OPTIONAL_ZERO_REGEX, "");
}
return phoneNumber;
}
replaceFirst而不是replaceAll更整洁,尽管我认为这在实践中不会有什么不同
用于证明其适用于非可选零的附加单元测试:
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeAndManyAdditionalZeroes_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+30 (005) 0511010");
assertEquals("+30050511010", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeWithoutCountryCodeAndManyAdditionalZeroes_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(005)0511010");
assertEquals("0050511010", compactPhoneNumber);
}
编辑:
另一种选择:
private static final String OPTIONAL_ZERO = "(0";
private static final String OPTIONAL_ZERO_REGEX = Pattern.quote(OPTIONAL_ZERO);
public static String removeOptionalZero(String phoneNumber)
{
if (phoneNumber.indexOf(OPTIONAL_ZERO) > 0)
{ // Only remove the optional zero when preceded by a country code
return phoneNumber.replaceAll(OPTIONAL_ZERO_REGEX, "");
}
return phoneNumber;
}
注:最后一个示例将删除
(0
,如果可能的话,将删除多次。但是,我认为不存在(0031)(012)3456789这样的情况,挂钩仅用于(部分)区号。如果没有,我很想听听!休息了一晚后,我想出了一个问题中提供的示例的简单版本:拆分正则表达式可以用于替换,而且更好,因为它还可以替换(012)区号的可选0(最后一个钩子仍将替换为所有其他可选字符)
除此之外,我的示例代码还删除了电话号码中所有额外的零(我认为这是Anubhava在评论中的部分意思)。我的新解决方案也解决了这一问题:
private static final String OPTIONAL_ZERO_REGEX = Pattern.quote("(0");
public static String removeOptionalZero(String phoneNumber)
{
String[] split = phoneNumber.split(OPTIONAL_ZERO_REGEX);
if (split.length == 2 && !split[0].isEmpty())
{ // Only remove the optional zero when preceded by a country code
return phoneNumber.replaceFirst(OPTIONAL_ZERO_REGEX, "");
}
return phoneNumber;
}
replaceFirst而不是replaceAll更整洁,尽管我认为这在实践中不会有什么不同
用于证明其适用于非可选零的附加单元测试:
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeAndManyAdditionalZeroes_ZeroIsRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("+30 (005) 0511010");
assertEquals("+30050511010", compactPhoneNumber);
}
@Test
public void removeOptionalCharacters_HooksAroundAreaCodeWithoutCountryCodeAndManyAdditionalZeroes_ZeroIsNotRemoved()
{
String compactPhoneNumber = PhoneNumber.removeOptionalCharacters("(005)0511010");
assertEquals("0050511010", compactPhoneNumber);
}
编辑:
另一种选择:
private static final String OPTIONAL_ZERO = "(0";
private static final String OPTIONAL_ZERO_REGEX = Pattern.quote(OPTIONAL_ZERO);
public static String removeOptionalZero(String phoneNumber)
{
if (phoneNumber.indexOf(OPTIONAL_ZERO) > 0)
{ // Only remove the optional zero when preceded by a country code
return phoneNumber.replaceAll(OPTIONAL_ZERO_REGEX, "");
}
return phoneNumber;
}
注:最后一个例子可能会多次删除
(0
。但是,我认为不存在像(0031)(012)3456789这样的情况,挂钩只在区号周围(部分)使用。如果没有,我很想听到它!关于+31 012 3456 789
和+30(0)呢12 3456 789
数字?您将此信息提交给“感觉脆弱”可能会更幸运这本身并不是一个技术问题。你所拥有的基本上是有效的,但可以做得更好。阿努巴瓦,你是什么意思?+31 012 3456 789没有区号,所以是一个有效的电话号码还是什么?也许你可以在你的解释中包括这个例子中的国家?如果+30(0)12 3456 789的区号是012(因此“hooked”0是可选的),我希望它成为+30123456789 Marsatomic,真的,谢谢,我不知道网站的代码审查部分!因为“最佳答案”也是有争议的,我不会在这里指定一个,只有在我认为它对我有帮助的情况下,我才会投赞成票。那么+31 012 3456 789
和+30(0)呢12 3456 789
数字?您可能会更幸运地将此提交给。“感觉脆弱”本身并不是一个真正的技术问题。您所拥有的基本上是有效的,但可以做得更好。Anubhava,你是什么意思?+31 012 3456 789没有区号,所以是一个有效的电话号码还是什么?也许您可以包括