我最近需要创建一个正则表达式来检查Javascript中的输入.输入可以是5或6个字符长,并且必须包含正好5个数字和一个可选空格,它们可以是字符串中的任何位置.我根本不是正则表达式,即使我尝试寻找更好的方法,我最终得到了这个:
(^\d{5}$)|(^ \d{5}$)|(^\d{5} $)|(^\d{1} \d{4}$)|(^\d{2} \d{3}$)|(^\d{3} \d{2}$)|(^\d{4} \d{1}$)
这就是我需要的,所以允许的输入是(如果0是任何数字)
'00000'
' 00000'
'0 0000'
'00 000'
'000 00'
'0000 0'
'00000 '
我怀疑这是与正则表达式实现这种匹配的唯一方法,但我还没有找到一种更清洁的方法.所以我的问题是,如何更好地编写?
谢谢.
编辑:
所以,这是可能的!Tom Lord的回答用正则表达式做了我需要的,所以我把它标记为我的问题的正确答案.
然而,在我发布这个问题后不久,我意识到我的想法不对,因为项目中的每个其他输入都很容易用正则表达式"验证",我立即假设我也可以用它来验证这个.
事实证明我可以这样做:
const validate = function(value) {
const v = value.replace(/\s/g, '')
const regex = new RegExp('^\\d{5}$');
return regex.test(v);
}
谢谢大家的精彩答案和想法!:)
Edit2:我忘了提一个可能非常重要的细节,即输入是有限的,所以用户最多只能输入6个字符.我很抱歉.
1> Tom Lord..:
注意:使用正则表达式来解决此问题可能不是最佳答案.如下所述,用简单的函数计算数字和空格可能更容易!
但是,由于问题是要求正则表达式的答案,并且在某些情况下,您可能被迫使用正则表达式解决此问题(例如,如果您被绑定到某个库的实现),以下答案可能会有所帮助:
此正则表达式匹配包含正好5位数的行:
^(?=(\D*\d){5}\D*$)
此正则表达式匹配包含一个可选空格的行:
^(?=[^ ]* ?[^ ]*$)
如果我们将它们放在一起,并确保字符串只包含数字和空格([\d ]*$
),我们得到:
^(?=(\D*\d){5}\D*$)(?=[^ ]* ?[^ ]*$)[\d ]*$
您也可以使用[\d ]{5,6}
而不是[\d ]*
在该模式的末尾,达到相同的效果.
演示
说明:
这个正则表达式使用前瞻.这些是零宽度模式匹配器,这意味着模式的两个部分都"锚定"到字符串的开头.
\d
表示"任何数字",\D
表示"任何非数字 ".
means "space", and [^ ]
意思是"任何非空间 ".
将\D*\d
被重复5次,以确保5位数字组成是的字符串中.
以下是正则表达式的可视化:
请注意,如果您确实希望"可选空间"包含选项卡之类的内容,那么您可以改为使用\s
和\S
.
更新:由于这个问题似乎已经引起了很大的关注,我想澄清一下这个答案.
我上面的答案有几个"更简单"的变体解决方案,例如:
// Only look for digits and spaces, not "non-digits" and "non-spaces":
^(?=( ?\d){5} *$)(?=\d* ?\d*$)
// Like above, but also simplifying the second lookahead:
^(?=( ?\d){5} *$)\d* ?\d*
// Or even splitting it into two, simpler, problems with an "or" operator:
^(?:\d{5}|(?=\d* \d*$).{6})$
上面每行的演示:1 2 3
或者,如果我们可以假设字符串不超过6个字符,那么即使这样就足够了:
^(?:\d{5}|\d* \d*)$
因此,考虑到这一点,为什么您可能希望使用原始解决方案,以解决类似的问题?因为它是通用的.再看看我的原始答案,用自由间距重写:
^
(?=(\D*\d){5}\D*$) # Must contain exactly 5 digits
(?=[^ ]* ?[^ ]*$) # Must contain 0 or 1 spaces
[\d ]*$ # Must contain ONLY digits and spaces
这种使用连续预测的模式可以在各种场景中使用,以编写高度结构化(并且可能令人惊讶地)易于扩展的模式.
例如,假设规则已更改,您现在想要匹配2-3个空格,1 .
和任意数量的连字符.实际上很容易更新正则表达式:
^
(?=(\D*\d){5}\D*$) # Must contain exactly 5 digits
(?=([^ ]* ){2,3}[^ ]*$) # Must contain 2 or 3 spaces
(?=[^.]*\.[^.]*$) # Must contain 1 period
[\d .-]*$ # Must contain ONLY digits, spaces, periods and hyphens
......因此,在总结,有是 "简单"的正则表达式的解决方案,并很可能更好的非正则表达式的解决方案OP的具体问题.但我提供的是一种通用的,可扩展的设计模式,用于匹配这种性质的模式.
方式太复杂了.在6个月内容易被误读或混淆.如果需求发生变化,太难改变.
2> le_m..:
我建议首先检查五个数字,^\d{5}$
或者预测^(?=\d* \d*$)
六个字符之间的数字之间的单个空格.{6}$
.
结合这些部分表达式得出^\d{5}$|^(?=\d* \d*$).{6}$
:
let regex = /^\d{5}$|^(?=\d* \d*$).{6}$/;
console.log(regex.test('00000')); // true
console.log(regex.test(' 00000')); // true
console.log(regex.test('00000 ')); // true
console.log(regex.test('00 000')); // true
console.log(regex.test(' 00000')); // false
console.log(regex.test('00000 ')); // false
console.log(regex.test('00 000')); // false
console.log(regex.test('00 0 00')); // false
console.log(regex.test('000 000')); // false
console.log(regex.test('0000')); // false
console.log(regex.test('000000')); // false
console.log(regex.test('000 0')); // false
console.log(regex.test('000 0x')); // false
console.log(regex.test('0000x0')); // false
console.log(regex.test('x00000')); // false
3> 小智..:
这对我来说似乎更直观,而且是O(n)
function isInputValid(input) {
const length = input.length;
if (length != 5 && length != 6) {
return false;
}
let spaceSeen = false;
let digitsSeen = 0;
for (let character of input) {
if (character === ' ') {
if (spaceSeen) {
return false;
}
spaceSeen = true;
}
else if (/^\d$/.test(character)) {
digitsSeen++;
}
else {
return false;
}
}
return digitsSeen == 5;
}