当谈到正则表达式时,我绝对不是最糟糕的,但是这个让我感到难过。
简而言之,这是我目前的代码。
$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
这是否可以使用正则表达式?
答案 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;
}
}
}