【问题标题】:regular expression to validate a pattern用于验证模式的正则表达式
【发布时间】:2020-10-09 17:32:33
【问题描述】:

我是正则表达式的新手,在我的项目中,我允许用户以简写形式和完整数字形式输入金额,我使用材料 UI 文本字段进行输入。

例如:

400k - shorthand, 

400.2k - shorthand, 

4m - shorthand,

500. - should work

500000 - full amount

一些模式用户不应该被允许输入示例是:

4.2.k, 

.3k, 

4...k

300.k

我写了下面的正则表达式,但它确实允许在数字后输入点。

textValue.match(/^[0-9]*(\.[0-9]{0,2})*([0-9km]{1})$/) && textValue.match(/^[\d]+/)

上面的代码第一个正则表达式验证模式,第二个正则表达式强制用户输入数字,因为数量不能以字符串开头,我写了两个单独的正则表达式,因为我不明白如何将它们放在一个正则表达式中,而那些正则表达式不接受数字后的点。请问谁能给出一个完美的正则表达式来在一个正则表达式中验证上述模式??

提前致谢

【问题讨论】:

  • this 有帮助吗?
  • 感谢您的回复,但它确实允许在数字示例 500 之后输入点。应该可以。
  • 你想在 500 之后允许一个点吗?
  • 是的,兄弟,因为我限制用户在 TextField 中输入任何其他字符,如果我不允许用户输入点,他不能 500.2k,因为我们不允许。
  • 5.5 也可以匹配吗?

标签: javascript regex reactjs validation material-ui


【解决方案1】:

使用交替(从来都不是最漂亮的)可以这样做:

^\d+([km]|\.|\.\d+[km])?$

Online Demo

  • ^ - 开始字符串 ancor。
  • d+ - 一位或多位数字。
  • ( - 打开捕获组(您可以使用非捕获)。
    • [km] - 单个字符“k”或“m”。
    • | - 交替 (OR)。
    • \.? - 文字点。
    • | - 交替 (OR)。
    • \.\d+[km] - 一个文字点,后跟至少一个数字和一个字符“k”或“m”。
    • )? - 关闭捕获组并将其设为可选
  • $ - 开始字符串 ancor。

【讨论】:

  • 这很好,很简短 ++。 (如果您不需要该组,您可以使其不捕获 (?:
【解决方案2】:

关于你尝试的模式

请注意,您不需要{1}。字符类[0-9km] 匹配字符km 或数字0-9 的1。这样,可能匹配的数字可能是 0-3 而不是 0-2。

对组使用量词 * 使其也可以匹配 400.25.22.22.22k


您可以使用此模式来验证示例。模式开头的 [0-9]+ 确保必须至少存在一个数字。

如果你想允许500. 你可以使用:

^[0-9]+(?:(?:\.[0-9]{1,2})?[km]?|\.)$

解释

  • ^ 字符串开始
  • [0-9]+匹配1+位数
  • (?:非捕获组
    • (?:\.[0-9]{1,2})? 匹配可选的带 2 位小数部分
    • [km]? 匹配可选km
    • |或者
    • \. 匹配单个点
  • )$字符串结束

Regex demo

let pattern = /^[0-9]+(?:(?:\.[0-9]{1,2})?[km]?|\.)$/;
[
  "400k",
  "400.2k",
  "4m",
  "500000",
  "500.",
  "300.k",
  "4.2.k",
  ".3k",
  "4...k",
].forEach(s => console.log(s + " --> " + pattern.test(s)));

另一种选择是仅在不直接跟随km 时匹配点

^[0-9]+(?:\.(?![km]))?\d*[km]?$

Regex

【讨论】:

  • 只有一个漏洞,它允许进入300.k,不应该发生。
  • @DaveSmith 您可以匹配可选的数字和公里,或者数字后跟一个点。查看更新。
  • 与您的第二个模式匹配 5.5 这是有道理的,但不确定 OP 是否需要它。如果他这样做,那么我的回答也不会迎合它,这很酷。像往常一样,你让我投了反对票 =)
【解决方案3】:

你可以试试:

^\d+\.?(?:\d+)?[KkMm]?(?<!\.[KkMm])$

上述正则表达式的解释:

^, $ - 分别匹配行的开头和结尾。

\d+ - 匹配数字 1 次或多次。

\.? - 表示出现 0 次或 1 次 .

[KkMm]? - 匹配来自上述字符类的可选字符。

(?&lt;!\.[KkMm]) - 表示与. 之后的字符不匹配的否定后视。

你可以在here.找到上述正则表达式的demo

const regex = /^\d+\.?(?:\d+)?[KkMm]?(?<!\.[KkMm])$/gm;
const str = `400K
4.2.K
4.3K
3.2M
300000
4....K
4K
500.
300.K`;
let m;

while ((m = regex.exec(str)) !== null) {
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`${match}`);
    });
}

使用交替的第二个有效解决方案:

你或许可以试试这个正则表达式来更有效地实现

^\d+(?:\.$|\.\d+)?[KkMm]?$

上述正则表达式的解释:

^, $ - 分别匹配行的开头和结尾。

\d+ - 匹配数字 1 次或多次。

(?:\.$|\.\d+)? - 代表非捕获组;匹配仅后跟 . 的数字或十进制数字。

[KkMm]? - 匹配提到的字符之一 0 次或 1 次。

你可以在here.找到上述正则表达式的demo

const regex = /^\d+(?:\.$|\.\d+)?[KkMm]?$/gm;
const str = `400K
4.2.K
4.3K
3.2M
300000
4....K
4K
500.
300.K`;
let m;

while ((m = regex.exec(str)) !== null) {
// The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
    console.log(`${match}`);
   });
}

【讨论】:

  • 只有一个缺陷,它允许进入300.k,不应该发生,点后不应该有k或m
  • 刚刚注意到我是唯一一个可能误解了这个问题的人。你的模式和@TheFourthBird 的模式都允许5.5。这听起来是合法的,但在 [km] 的背景下它也可能是错误的,因为你不能说 5.5。听起来很模糊?无论哪种方式,OP都应该澄清=)
猜你喜欢
  • 2016-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-29
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 2015-05-14
相关资源
最近更新 更多