荷兰语电话号码的正则表达式

时间:2015-10-14 12:09:39

标签: php regex

当谈到正则表达式时,我绝对不是最糟糕的,但是这个让我感到难过。

简而言之,这是我目前的代码。

$aNumbers = array(
    '612345678',
    '546123465',
    '131234567',
    '+31(0)612345678'
);

foreach($aNumbers as $sNumber) {
    $aMatches = array();
    $sNumber = preg_replace('/(\(0\)|[^\d]+)/', '', $sNumber);

    preg_match('/(\d{1,2})?(\d{3})(\d{3})(\d{3})$/', $sNumber, $aMatches);

    var_dump($sNumber);
    var_dump($aMatches);
}

简单地说,我想匹配电话号码的特定格式,以确保统一显示。

+31(0)612345678
+31(0)131234567

剥离的都是没有+和(0)。 减少部分:

31     6    123 456 78
Country Net Number
31     13   123 456 78
Country Net Number

现在,在某些情况下,+ 31(或+1,+ 222)是可选的。总是包含6和13,但作为一种有趣的转折,以下格式也是可能的:

31     546  123 456
Country Net Number

这是否可以使用正则表达式?

2 个答案:

答案 0 :(得分:1)

我已经回答了其中一些类型的问题,我的策略是识别传达意义的格式或数字关系的某些部分,并摆脱其余部分。

One of my examples that parses non-NANP number formatting在解析表达式中使用有效区域代码列表,并在存在时标识国家/地区代码。它提取国家代码,区号,然后是数字的其余部分。

或您所在的国家/地区,我假设HansM的答案中的区域/网络/地区代码列表正确或易于替换,因此我猜这种正则表达式的修改可能有用:

^[ -]*(\+31)?[ -]*[(0)]*[ -]*(7|43|32|45|33|49|39|31|47|34|46|41|90|44|351|353|358)[ -]*((?:\d[ -]*)+)

首先匹配国家/地区代码(如果存在),并将其存储在反向引用1中,然后忽略单个零。然后它将匹配一个区域/网络/区域代码并将其存储在反向引用2.它将获得任意数量的数字(一个或多个),与短划线(-)和/或空格混合()并将其存储在反向引用3

在此之后,您可以解析第三个编号组的有效性或进一步重新格式化

我在Regex 101上测试它,但是我可以使用一个可接受和不可接受的输入列表,以及在可接受的情况下应该如何重新格式化...

[编辑]

我已使用this list of city codes for the Netherlands并因此修改了表达式:

^[ -]*(\+31)?[ -]*[(0)]*[ -]*([123457]0|23|24|26|35|45|71|73|570)[ -]*((?:\d[ -]*)+)

执行以下解析:

input                     (1)    (2)    (3) 
---------------------    ------ ------ ---------------
0707123456                       70     7123456
0267-123456                      26     7-123456
0407-12 34 56                    40     7-12 34 56
0570123456                       570    123456
07312345                         73     12345
+31(0)734423211           +31    73     4423211 

但我仍然不知道这对你有用吗<​​/ p>

[编辑2]

维基百科的内容似乎是a more comprehensive list of codes

  

010,0111,0113,0114,0115,0117,0118,013,015,0161,0162,0164,0165,0166,0167,0168,0172,0174,0180,0181,0182,0183,0184,0186 ,0187,020,0222,0223,0224,0226,0227,0228,0229,023,024,0251,0252,0255,026,0294,0297,0299,030,0313,0314,0315,0316,0317,0318 ,0320,0321,033,0341,0342,0343,0344,0345,0346,0347,0348,035,036,038,040,0411,0412,0413,0416,0418,043,045,046,0475,0478 ,0481,0485,0486,0487,0488,0492,0493,0495,0497,0499,050,0511,0512,0513,0514,0515,0516,0517,0518,0519,0521,0522,0523,0524,0525 ,0527,0528,0529,053,0541,0543,0544,0545,0546,0547,0548,055,0561,0562,0566,0570,0571,0572,0573,0575,0577,0578,058,0591,0592 ,0593,0594,0595,0596,0597,0598,0599,070,071,072,073,074,075,076,077,078,079

可以在代码选择部分中使用(如果您希望更容易阅读和更新):

10|111|113|114|115|117|118|13|15|161|162|164|165|166|167|168|172|174|180|181|182|183|184|186|187|20|222|223|224|226|227|228|229|23|24|251|252|255|26|294|297|299|30|313|314|315|316|317|318|320|321|33|341|342|343|344|345|346|347|348|35|36|38|40|411|412|413|416|418|43|45|46|475|478|481|485|486|487|488|492|493|495|497|499|50|511|512|513|514|515|516|517|518|519|521|522|523|524|525|527|528|529|53|541|543|544|545|546|547|548|55|561|562|566|570|571|572|573|575|577|578|58|591|592|593|594|595|596|597|598|599|70|71|72|73|74|75|76|77|78|79

或者像这样(如果你更喜欢对表达式进行更有效的评估):

1([035]|1[134578]|6[124-8]|7[24]|8[0-467])|2([0346]|2[2346-9]|5[125]|9[479])|3([03568]|1[34-8]|2[01]|4[1-8])|4([0356]|1[12368]|7[58]|8[15-8]|9[23579])|5([0358]|[19][1-9]|2[1-5789]|4[13-8]|6[126]|7[0-3578])|7[0-9]

答案 1 :(得分:0)

我使用了nuget包libphonenumber-csharp。

这有助于我创建一个(荷兰语)电话号码验证器,这里是一个代码片段,没有我的解决方案的其他部分,它将无法编译,但至少你可以知道如何处理这个。

  public override void Validate()
    {
        ValidationMessages = new Dictionary<string, string>();
        ErrorMessage = string.Empty;
        string phoneNumber;
        string countryCode = _defaultCountryCode;

        // If the phoneNumber is not required, it is allowed to be empty.
        // So in that case isValid gets defaultvalue true
        bool isValid = (!_isRequired);

        if (!string.IsNullOrEmpty(_phoneNumber))
        {
            var phoneUtil = PhoneNumberUtil.GetInstance();
            try
            {
                phoneNumber = PhoneNumbers.PhoneNumberUtil.Normalize(_phoneNumber);
                countryCode = PhoneNumberUtil2.GetRegionCode(phoneNumber, _defaultCountryCode);
                PhoneNumber oPhoneNumber = phoneUtil.Parse(phoneNumber, countryCode);
                var t1 = oPhoneNumber.NationalNumber;
                var t2 = oPhoneNumber.CountryCode;
                var formattedNo = phoneUtil.Format(oPhoneNumber, PhoneNumberFormat.E164);
                isValid = PhoneNumbers.PhoneNumberUtil.IsViablePhoneNumber(formattedNo);
            }
            catch (NumberParseException e)
            {
                var err = e.ToString();
                isValid = false;
            }
        }

        if ((isValid) && (!string.IsNullOrEmpty(_phoneNumber)))
        {
            Regex regexValidator = null;
            string regex;

            // Additional validations for Dutch phone numbers as LibPhoneNumber is to graceful as it comes to
            // thinking if a number is valid.
            switch (countryCode)
            {
                case "NL":

                    if (_phoneNumber.StartsWith("0800") || _phoneNumber.StartsWith("0900"))
                    {
                        // 0800/0900 numbers
                        regex = @"((0800|0900)(-| )?[0-9]{4}([0-9]{3})?$)";
                        regexValidator = new Regex(regex);
                        isValid = regexValidator.IsMatch(_phoneNumber);
                    }
                    else
                    {
                        string phoneNumberCheck = _phoneNumber.Replace("(", "").Replace(")", "").Replace("-", "").Replace(" ", "");

                        regex = @"^(0031|\+31|0)[1-9][0-9]{8}$";

                        regexValidator = new Regex(regex);
                        isValid = regexValidator.IsMatch(phoneNumberCheck);
                    }
                    break;
            }
        }
        if (!isValid)
        {
            ErrorMessage = string.Format(TextProvider.Get(TextProviderConstants.ValMsg_IsInAnIncorrectFormat_0),
                ColumnInfoProvider.GetLabel(_labelKey));

            ValidationMessages.Add(_messageKey, ErrorMessage);
        }
    }

同样有用的可能是我的类PhoneNumberUtil2,它基于nuget包libphonenumber-csharp构建:

// Code start
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using PhoneNumbers;

namespace ProjectName.Logic.Miscellaneous
{
    public class PhoneNumberUtil2
    {
        /// <summary>
        /// Returns the alphanumeric country code for a normalized phonenumber. If a phonenumber does not contain 
        /// an international numeric country code, the default country code for the website is returned.
        /// This works for 17 countries: NL, GB, FR, DE, BE, AU, SE, NO, IT, TK, RU, CH, DK, IR, PT, ES, FI
        /// </summary>
        /// <param name="normalizedPhoneNumber"></param>
        /// <param name="defaultCountryCode"> </param>
        /// <returns></returns>
        public static string GetRegionCode(string normalizedPhoneNumber, string defaultCountryCode)
        {
            if (normalizedPhoneNumber.Length > 10)
            {
                var dict = new Dictionary<string, string>();
                dict.Add("7", "RU");
                dict.Add("43", "AT");
                dict.Add("32", "BE");
                dict.Add("45", "DK");
                dict.Add("33", "FR");
                dict.Add("49", "DE");
                dict.Add("39", "IT");
                dict.Add("31", "NL");
                dict.Add("47", "NO");
                dict.Add("34", "ES");
                dict.Add("46", "SE");
                dict.Add("41", "CH");
                dict.Add("90", "TR");
                dict.Add("44", "GB");
                dict.Add("351", "PT");
                dict.Add("353", "IE");
                dict.Add("358", "FI");

                // First check 3-digits International Calling Codes
                if (dict.ContainsKey(normalizedPhoneNumber.Substring(0, 3)))
                {
                    return dict[normalizedPhoneNumber.Substring(0, 3)];
                }

                // Then 2-digits International Calling Codes 
                if (dict.ContainsKey(normalizedPhoneNumber.Substring(0, 2)))
                {
                    return dict[normalizedPhoneNumber.Substring(0, 2)];
                }

                // And finally 1-digit International Calling Codes
                if (dict.ContainsKey(normalizedPhoneNumber.Substring(0, 1)))
                {
                    return dict[normalizedPhoneNumber.Substring(0, 1)];
                }
            }
            return defaultCountryCode;
        }

    }
}