【问题标题】:Javascript regex for money with max length最大长度的 Javascript 正则表达式
【发布时间】:2021-05-19 10:21:09
【问题描述】:

我想验证一个数字最大长度为 13 且小数点后 2 位的货币字符串。我有一个逗号作为小数分隔符和一个句点作为千位分隔符。

我有这个正则表达式:

/^(\d{1}\.)?(\d+\.?)+(,\d{2})?$/

对于 sintax 是有效的,但对于最大长度无效。我需要在这个正则表达式中添加什么?

例如,这些字符串必须是有效的:

1.000.000.000.000
1.000.000.000.000,00
1
1,00
123,45

而且这些一定是无效的:

10.000.000.000.000
10.000.000.000.000,00
10.000.000.000.000.000
10.000.000.000.000.000,00

【问题讨论】:

  • 如果您需要确保字符串中的数字少于 16 位,请在 ^ 之后添加 (?!(?:\D*\d){16})。
  • 感谢@WiktorStribiżew 的回答,是有效的,但比其他答案要复杂一些。
  • 我不认为(?=[\d.]{1,17}(?:,\d{2})?$) 比(?!(?:\D*\d){16})“简单”,但请随意使用最适合您的任何解决方案。 (?!(?:\D*\d){16}) 语法是通用的,可以忽略任何非数字的计数。 (?![\d.]{18}) 遵循类似的逻辑(尽管它必须依赖后续的消费模式才能正常工作),但更具体,因为它只将点匹配为非数字。
  • 抱歉,我不是正则表达式专家,我无法在 regex101 或类似页面中尝试您的解决方案。但是我了解您的解决方案,无法尝试,这有点复杂。非常感谢您的宝贵时间。问候。

标签: javascript regex currency


【解决方案1】:

也许尝试使用负前瞻来断言位置后面不是 18 位数字/点:

^(?![\d.]{18})\d{1,3}(?:\.\d{3})*(?:,\d\d?)?$

查看在线demo。这里假设您也允许使用一位小数。

  • ^ - 打开线锚。
  • (?![\d.]{18}) - 负前瞻以防止提前 18 位数字/点。
  • \d{1,3} - 一到三位数。
  • (?:\.\d{3})* - 一个由文字点组成的非捕获组,后跟三个数字,乘数为 0+。
  • (?:,\d\d?)? - 可选的非捕获组,逗号后跟 1 或两位数字。删除问号,使小数点后第二位不可选。
  • $ - 结束线锚。

【讨论】:

  • @Corporativo。不客气。随意接受一个对你有用的答案来关闭线程。
【解决方案2】:

您可以使用此正则表达式进行验证:

^(?=[\d.]{1,17}(?:,\d{2})?$)\d{1,3}(?:\.\d{3})*(?:,\d{2})?$

RegEx Demo

正则表达式详细信息:

  • ^:开始
  • (?=[\d.]{1,17}(?:,\d{2})?$):先行匹配点或数字 1 到 17 次,后跟可选的逗号和 2 位数字
  • \d{1,3}:匹配 1 到 3 位数字
  • (?:\.\d{3})*:匹配 . 后跟 3 位数字。重复此组 0 次或多次
  • (?:,\d{2})?:匹配可选 , 后跟 2 个十进制数字
  • $:结束

【讨论】:

  • 感谢 anubhava 的回答,是我需要的。问候。
【解决方案3】:

90% 的情况下,有比使用正则表达式更好的解决方案。最好将您的字符串转换为实数,然后与您的限制(即9999999999999.99)进行比较。

// Pass a string
function convertStr(string) {
  /*
  Remove all '.'
  Replace all ',' with '.'
  */
  let numStr = string.split('.').join('').replaceAll(',', '.');
  // Convert modified string into a real number
  let realNum = parseFloat(numStr);
  /*
  if converted string is a real number...
  round it to two decimal places and return it
  Otherwise return false
  */
  return !Number.isNaN(realNum) ? Math.round((realNum + Number.EPSILON) * 100) / 100 : false;
}

// Pass a string and the maxed number 
function numLimit(string, limit) {
  // Get the result of convertString()
  let number = convertStr(string);
  // if the result is equal to or less than limit...
  if (number <= limit) {
    return true;
  } else {
    return false;
  }
}

const limit = 9999999999999.99;
const valid = ['1.000.000.000.000',
  '1.000.000.000.000,00', '1', '1,00', '123,45'
];
const invalid = ['10.000.000.000.000', '10.000.000.000.000,00', '10.000.000.000.000.000', '10.000.000.000.000.000,00'];

let validResults = valid.map(str => numLimit(str, limit));

let invalidResults = invalid.map(str => numLimit(str, limit));

console.log('valid: ' + validResults);
console.log('invalid: ' + invalidResults);

【讨论】:

  • 感谢 zer00ne 为 regex 提供了一个替代解决方案,看起来不错,但是,如果 regex 在一行中工作正常,为什么要制作这个解决方案?问候。
  • 当输入参数稍有不同时,尝试调整这一行。我可以精简它,但像你这样的新手不会那么容易理解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多