regex 创建正则表达式以匹配大数字

quhf5bfb  于 12个月前  发布在  其他
关注(0)|答案(4)|浏览(154)

我从后端得到一个响应,作为文本,我必须找到一个匹配的数字,这是最小的16位数的长度。
假设我有这样的数据:

{"BIG_INT": 123456789012345675,"BIG_INT_ARRAY_SINGLE": [123456789012345676],"BIG_INT_ARRAY_MULTIPLE": [123456789012345661,12345678901234562,12345678901234563,12345678901234564],"STRING_BIG_INT_ARRAY": "[12345678901234567,12345678901234567, 12345678901234567,12345678901234567]","STRING_BIG_INT":"12345678901234567","BIG_INT_FLOATING_DECIMAL": 12345678901234567.76543210987654321}

字符串
在某些情况下,它不应该与数字匹配:
1.如果数字用双引号括起来:
("STRING_BIG_INT":"12345678901234567"1.如果数字在字符串封闭数组中:"STRING_BIG_INT_ARRAY":"[12345678901234567,12345678901234567]"个 1.如果数字是小数:"BIG_INT_FLOATING_DECIMAL":12345678901234567.76543210987654321个 它应该匹配一个数字的条件: 1.如果它是一个整数"BIG_INT": 123456789012345675,这里的值123456789012345675应该得到匹配。 1.如果它在数组"BIG_INT_ARRAY_MULTIPLE":[123456789012345678,123456789012345678]中,这两个数字应该分别匹配。 我尝试了这个正则表达式->(:\s*)([[])?(\d{16,})(\s*)([,}]])这个表达式的一个缺点是,如果我们有一个数字数组"test":[12345678901234567,1236543858688483444,26531562351351374343]`,这里我的表达式只匹配第一个数字。如果数组没有用双引号括起来,我想匹配数组中的所有数字。
在匹配所有数字之后,我有这样的代码来将数字替换为一个Bignumformate(例如:“16536235653725645345 n”),并提取其中的值部分并将数字转换为Bignumformate。

const bigNumsRegExp = new RegExp(/(:\s*)([\[])?(\d{16,})(\s*)([,\}\]])/g);
`const serializedData = data.replace(bigNumsRegExp, '$1$2"$3n"$4$5');`


所以我只需要一个正则表达式,它只匹配BIG_INTBIG_INT_ARRAY_SINGLEBIG_INT_ARRAY_MULTIPLE中的数字。
任何人的任何帮助都值得赞赏。
谢谢

1szpjjfi

1szpjjfi1#

有一个JSON.parse源文本访问建议,目前在第3阶段,它预见了对JSON.parse可用的reviver回调的第三个参数。这个第三个参数提供了对解析值的源字符串的访问(第二个参数),并使任何正则表达式操作都不必要。
您的使用情形是此建议书的动机。
在撰写本文时,它可以在Chrome和Edge中使用,但还没有Firefox。
这会产生下列程式码,只有在支援此功能时,才会建立BigInt值:

function reviver(key, value, info)  {
    const source = info?.source;
    if (!source 
            || typeof value !== "number"
            || Number.MIN_SAFE_INTEGER <= value && value <= Number.MAX_SAFE_INTEGER
            || source.includes(".")
            || source.toLowerCase().includes("e")) {
        return value;
    }
    return BigInt(source);
}

let s = '{"BIG_INT": 123456789012345675,"BIG_INT_ARRAY_SINGLE": [123456789012345676],"BIG_INT_ARRAY_MULTIPLE": [123456789012345661,12345678901234562,12345678901234563,12345678901234564],"STRING_BIG_INT_ARRAY": "[12345678901234567,12345678901234567, 12345678901234567,12345678901234567]","STRING_BIG_INT":"12345678901234567","BIG_INT_FLOATING_DECIMAL": 12345678901234567.76543210987654321}';

const result = JSON.parse(s, reviver);

字符串
在我的浏览器中,这会将下列对象指派给result

{
    BIG_INT: 123456789012345675n, 
    BIG_INT_ARRAY_SINGLE: [
        123456789012345675n
    ], 
    BIG_INT_ARRAY_MULTIPLE: [
        123456789012345661n,
        12345678901234562n,
        12345678901234563n,
        12345678901234564n
    ],
    STRING_BIG_INT_ARRAY: "[12345678901234567,12345678901234567, 12345678901234567,12345678901234567]",
    STRING_BIG_INT: "12345678901234567",
    BIG_INT_FLOATING_DECIMAL: 12345678901234568
}


请注意,reviver不将BIG_INT_FLOATING_DECIMAL的值转换为BigInt,因为它在源代码中有一个小数点。我还包括了一个科学记数法的测试(在这种情况下不生成BigInt)。当然,您可以用不同的方式处理这些情况。

des4xlb0

des4xlb02#

没有什么复杂的,因为JSON的类型非常有限:

  • 把你需要保存的东西放在一个捕获组中(字符串和浮点数,带指数的数字)
  • 测试捕获组是否存在于替换箭头函数中,并选择要返回的内容。

在整数周围放置双引号的示例(需要时):

let source = `{
  "BIG_INT": 123456789012345675,
  "BIG_INT_ARRAY_SINGLE": [123456789012345676],
  "BIG_INT_ARRAY_MULTIPLE": [123456789012345661,12345678901234562,12345678901234563,12345678901234564],
  "STRING_BIG_INT_ARRAY": "[12345678901234567,12345678901234567, 12345678901234567,12345678901234567]",
  "STRING_BIG_INT":"12345678901234567",
  "BIG_INT_FLOATING_DECIMAL": 12345678901234567.76543210987654321
}`;

const pattern = /("[^\\"]*(?:\\.[^\\"]*)*"|\d+\.\d*(?:e[-+]?\d+)?|\d+(?:e[-+]?\d+))|\d+/gi;

let result = source.replace(pattern, (m, g1) => g1 ? g1: `"${m}"`);

console.log(result);

字符串

d8tt03nd

d8tt03nd3#

这是一个解析https://tsplay.dev/wXyloN的JSON恢复器

function JsonParseWithBigints(json: string) {
  const g = /\b\d+(\.\d+)?\b/g;
  let matches = s.match(g) ?? []
  return JSON.parse(s, (key, value) => {
    if (typeof value === 'number') {
      let s = matches.shift()!
      if (+s !== value) throw new Error(s + '!=' + value)
      if (s === `${value}`) return value;
      if (!s.includes('.')) {
        return BigInt(s)
      }
      let [d, f] = s.split('.')
      return { value: BigInt(d + f), exp: -f.length }
    }
    if (typeof value === 'string') {
      for (let k of value.match(g) ?? []) {
        let s = matches.shift()!
        if (s !== k) throw new Error(s + '!=' + value)
      }
    }
    return value
  })
}

字符串
它解析JSON,同时将解析时会丢失精度的数字替换为从原始字符串中获取的BigInt变体
以下是它为您的输入生成的内容:

{
  "BIG_INT": 1123456789012345675n,
  "BIG_INT_ARRAY_SINGLE": [
    2123456789012345676n
  ],
  "BIG_INT_ARRAY_MULTIPLE": [
    3123456789012345661n,
    412345678901234562n,
    512345678901234563n,
    612345678901234564n
  ],
  "STRING_BIG_INT_ARRAY": "[712345678901234567,812345678901234567, 912345678901234567,1012345678901234567]",
  "STRING_BIG_INT": "1112345678901234567",
  "BIG_INT_FLOATING_DECIMAL": {
    "value": 121234567890123456776543210987654321n,
    "exp": -17
  }
}

wsxa1bj1

wsxa1bj14#

试试下面的匹配模式。

(?<=\"BIG_INT(?:_ARRAY_(?:SINGLE|MULTIPLE))?\":\s\[?)\d{16,}(?:,\d{16,})*

字符串
这里有一个例子。

s = '{"BIG_INT": 123456789012345675,"BIG_INT_ARRAY_SINGLE": [123456789012345676],"BIG_INT_ARRAY_MULTIPLE": [123456789012345661,12345678901234562,12345678901234563,12345678901234564],"STRING_BIG_INT_ARRAY": "[12345678901234567,12345678901234567, 12345678901234567,12345678901234567]","STRING_BIG_INT":"12345678901234567","BIG_INT_FLOATING_DECIMAL": 12345678901234567.76543210987654321}'
var p = /(?<=\"BIG_INT(?:_ARRAY_(?:SINGLE|MULTIPLE))?\":\s\[?)\d{16,}(?:,\d{16,})*/g
a = []
for (var x of s.matchAll(p)) a.push(... String(x).split(','))

console.log(a)

相关问题