使用regex、java从电话号码中删除可选零

使用regex、java从电话号码中删除可选零,java,android,regex,phone-number,Java,Android,Regex,Phone Number,我有一个java类(称为PhoneNumber)来验证和处理电话号码 我自己编写了最后一个方法(删除可选零),但我希望它更简单一点(可能使用正则表达式识别可选零,并使用相同的正则表达式删除它,就像optional\u PHONE\u NUMBER\u CHARACTERSpart)。这段代码感觉很脆弱,不是100%正确,尽管我认为它满足了我的需要,涵盖了我能想到的所有单元测试 谁能给我一个明确的例子,包括一个适当的正则表达式?(也欢迎其他简单的解决方案) 如您所见,我提取了用于删除可选字符的代码

我有一个java类(称为
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没有区号,所以是一个有效的电话号码还是什么?也许您可以包括