用于匹配特定 phone 数字的正则表达式
RegEx for matching specific phone numbers
我正在尝试查看一个字符串是否与我所在国家/地区的 phone 数字格式匹配,即区号(两个数字前面可能有也可能没有 0,也可能在括号之间)后跟 8 或 9 位数字,其中最后 4 位数字之前可能有一个短划线字符。
这些是一些有效的格式:
'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'
'(00) 0000-0000'
'(000) 000000000'
到目前为止,这是我的工作表达式:
p = /0?\d{2}\s?-?\s?\d{4,5}\s?-?\s?\d{4}/
我尝试使用条件判断区号是否在带 /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}/
的括号内,但出现 (repl):1: target of repeat operator is not specified: /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}
错误。
我做错了什么?
可能有几种方法可以验证这些数字。一种方法是,我们写下所有可能的 phone 数字,然后为它写一个表达式。也许,类似于:
[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}
测试
re = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/m
str = '\'00 00000000\'
\'000-000000000\'
\'000 00000-0000\'
\'00 0000-0000\''
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
演示
此代码段只是为了显示捕获组并且表达式可能有效:
const regex = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/gm;
const str = `'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
正则表达式
如果不需要此表达式,可以在 regex101.com 中对其进行修改或更改。
正则表达式电路
jex.im 也有助于形象化表达。
编辑 1:
在 ()
的情况下,我们想在我们的初始表达式中添加两个负向后视。也许,similar to this:
\(?[0-9]{2,3}\)?(\s|-)[0-9]{4,5}-?[0-9]{3,4}
不要使用正则表达式验证 phone 数字。我打赌你不想排除那些偶尔输入 2 个后续空格或其他内容的人。
而是过滤掉所有 non-digits 和前导零,然后进行验证。像这样:
number.gsub(/\D+/, '').gsub(/\A0+/) =~ /\d{8,9}/
我不确定开箱即用是否满足您的需求,但我敢打赌您已经明白了。毕竟,[000]1234 56789
是一个可以理解的phone数字。
我相信你可以使用下面的正则表达式。
R = /
\A # match beginning of string
(?: # begin a non-capture group
\(0?\d{2}\) # match '(' then an optional `0` then two digits then ')'
| # or
0?\d{2} # match an optional `0` then two digits
) # end the non-capture group
(?: # begin a non-capture group
[ ]+ # match one or more spaces
| # or
- # match a hyphen
) # end the non-capture group
\d{4,5} # match 4 or 5 digits
-? # optionally match a hyphen
\d{4} # match 4 digits
\z # match end of string
/x # free-spacing regex definition mode
arr = [
'00 00000000',
'000-000000000',
'000 00000-0000',
'00 0000-0000',
'(00) 0000-0000',
'(000) 000000000',
'(000 000000000',
'(0000) 000000000'
]
arr.map { |s| s.match? R }
#=> [true, true, true, true, true, true, false, false]
正则表达式约定俗成如下
R = /\A(?:\(0?\d{2}\)|0?\d{2})(?: +|-)\d{4,5}-?\d{4}\z/
如果前导数字不能为零,则应按如下方式更改。 (例如,如果 '001-123456789'
和 '(12)-023456789'
无效。)
R = /\A(?:\(0?[1-9]\d\)|0?\[1-9]\d)(?: +|-)[1-9]\d{3,4}-?\d{4}\z/
我的回答解决了您对可选括号的 conditional 想法。
Ruby 从 v2.0 开始支持条件。 syntax 是 (?(A)X|Y)
:如果 A 为真,则 X 否则 Y。
- 在开头放置一个包含左括号的 optional capturing group:
^(\()?
- 稍后在模式中的任何地方检查它是否成功:
(?(1)\) |[ -])
如果成功:需要结束 )
后跟 space
|
否则:[ -]
space 或破折号。
所以带条件的整个模式可以是
^(\()?0?\d{2}(?(1)\) |[ -])\d{4,5}[ -]?\d{4}$
见demo at Rubular or Regex101。根据您的需要进一步调整。
使用交替 (?:\(abc\)|abc)
的替代方法,@CarySwoveland 已经回答了,但我认为 @AlekseiMatiushkin 的回答肯定会让生活更轻松。
不要这样做,除非你知道你在非常、非常有限的范围内工作,例如
- 这些数字被传递到一个只接受特定格式的系统,因此您知道这些格式完全正确,其他格式都行不通
- 这些数字只是由人类读取的,因此您可以让他们自己弄明白,而不必验证任何东西
否则你应该使用像 https://github.com/mobi/telephone_number (inspired by Google's libphonenumber)
这样强大的库
我正在尝试查看一个字符串是否与我所在国家/地区的 phone 数字格式匹配,即区号(两个数字前面可能有也可能没有 0,也可能在括号之间)后跟 8 或 9 位数字,其中最后 4 位数字之前可能有一个短划线字符。 这些是一些有效的格式:
'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'
'(00) 0000-0000'
'(000) 000000000'
到目前为止,这是我的工作表达式:
p = /0?\d{2}\s?-?\s?\d{4,5}\s?-?\s?\d{4}/
我尝试使用条件判断区号是否在带 /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}/
的括号内,但出现 (repl):1: target of repeat operator is not specified: /?(\() 0?\d{2}\)|0?\d{2} \s?-?\s?\d{4,5}\s?-?\s?\d{4}
错误。
我做错了什么?
可能有几种方法可以验证这些数字。一种方法是,我们写下所有可能的 phone 数字,然后为它写一个表达式。也许,类似于:
[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}
测试
re = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/m
str = '\'00 00000000\'
\'000-000000000\'
\'000 00000-0000\'
\'00 0000-0000\''
# Print the match result
str.scan(re) do |match|
puts match.to_s
end
演示
此代码段只是为了显示捕获组并且表达式可能有效:
const regex = /[0-9]{2,3}(\s|-)[0-9]{4,5}-?[0-9]{3,4}/gm;
const str = `'00 00000000'
'000-000000000'
'000 00000-0000'
'00 0000-0000'`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
正则表达式
如果不需要此表达式,可以在 regex101.com 中对其进行修改或更改。
正则表达式电路
jex.im 也有助于形象化表达。
编辑 1:
在 ()
的情况下,我们想在我们的初始表达式中添加两个负向后视。也许,similar to this:
\(?[0-9]{2,3}\)?(\s|-)[0-9]{4,5}-?[0-9]{3,4}
不要使用正则表达式验证 phone 数字。我打赌你不想排除那些偶尔输入 2 个后续空格或其他内容的人。
而是过滤掉所有 non-digits 和前导零,然后进行验证。像这样:
number.gsub(/\D+/, '').gsub(/\A0+/) =~ /\d{8,9}/
我不确定开箱即用是否满足您的需求,但我敢打赌您已经明白了。毕竟,[000]1234 56789
是一个可以理解的phone数字。
我相信你可以使用下面的正则表达式。
R = /
\A # match beginning of string
(?: # begin a non-capture group
\(0?\d{2}\) # match '(' then an optional `0` then two digits then ')'
| # or
0?\d{2} # match an optional `0` then two digits
) # end the non-capture group
(?: # begin a non-capture group
[ ]+ # match one or more spaces
| # or
- # match a hyphen
) # end the non-capture group
\d{4,5} # match 4 or 5 digits
-? # optionally match a hyphen
\d{4} # match 4 digits
\z # match end of string
/x # free-spacing regex definition mode
arr = [
'00 00000000',
'000-000000000',
'000 00000-0000',
'00 0000-0000',
'(00) 0000-0000',
'(000) 000000000',
'(000 000000000',
'(0000) 000000000'
]
arr.map { |s| s.match? R }
#=> [true, true, true, true, true, true, false, false]
正则表达式约定俗成如下
R = /\A(?:\(0?\d{2}\)|0?\d{2})(?: +|-)\d{4,5}-?\d{4}\z/
如果前导数字不能为零,则应按如下方式更改。 (例如,如果 '001-123456789'
和 '(12)-023456789'
无效。)
R = /\A(?:\(0?[1-9]\d\)|0?\[1-9]\d)(?: +|-)[1-9]\d{3,4}-?\d{4}\z/
我的回答解决了您对可选括号的 conditional 想法。
Ruby 从 v2.0 开始支持条件。 syntax 是 (?(A)X|Y)
:如果 A 为真,则 X 否则 Y。
- 在开头放置一个包含左括号的 optional capturing group:
^(\()?
- 稍后在模式中的任何地方检查它是否成功:
(?(1)\) |[ -])
如果成功:需要结束)
后跟 space|
否则:[ -]
space 或破折号。
所以带条件的整个模式可以是
^(\()?0?\d{2}(?(1)\) |[ -])\d{4,5}[ -]?\d{4}$
见demo at Rubular or Regex101。根据您的需要进一步调整。
使用交替 (?:\(abc\)|abc)
的替代方法,@CarySwoveland 已经回答了,但我认为 @AlekseiMatiushkin 的回答肯定会让生活更轻松。
不要这样做,除非你知道你在非常、非常有限的范围内工作,例如
- 这些数字被传递到一个只接受特定格式的系统,因此您知道这些格式完全正确,其他格式都行不通
- 这些数字只是由人类读取的,因此您可以让他们自己弄明白,而不必验证任何东西
否则你应该使用像 https://github.com/mobi/telephone_number (inspired by Google's libphonenumber)
这样强大的库