【问题标题】:JavaScript regex to match numbers in arrayJavaScript 正则表达式匹配数组中的数字
【发布时间】:2017-09-19 06:06:44
【问题描述】:

我有以下文字:

 {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}

我需要匹配并在数组“values”中的数字周围加上引号,所以它的结果应该是:

 {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": ["3.523422","0","-323123123","3.423","9223372036854775807","0","test 123.32","0","0","","0","0"]}}

数字可以是浮点数、负数和普通数。

【问题讨论】:

  • 使用 JSON 解析器。如果我可以评论十几次,我会的。您可能会一直使用正则表达式,但我认为正则表达式不应该是这里的主要解决方案。
  • 为什么要把数字变成字符串呢?如果我学到了一件事,那就是让原始类型保留它们的原生类型。
  • 很可能您采用了错误的方法,无需将数字转换为字符串。因为它们是数字...
  • 我正在转换它们,因为我需要处理 JS 不支持的大数字,我只需要获取这些值并将它们放在页面上。大数字是这样的:9223372036854775807。试着把它像一个数字一样放在你的控制台上。如果有更好的方法可以做到这一点,我会很乐意使用它,但我不知道。所以我将它们转换为字符串,然后用 JSON 解析器解析它们。
  • 如何生成这个 JSON?为什么不在构建这个 JSON 之前/时制作 obj.data.valuesString[]?正如您所说,当您只想将它们放在页面上时,这些数字是数字而不是字符串真的有问题吗?这么多问题,只是为了避免这种黑客攻击

标签: javascript regex replace match


【解决方案1】:

您可以循环遍历数据并将其转换为字符串,如下所示:

var data =  {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}

var values = [];

for (var i = 0 ; i < data.data.values.length ; i ++) {
    values.push(String(data.data.values[i]));
}

data.data.values = values;

console.log(data);

【讨论】:

    【解决方案2】:

    您只需有一个循环来检查值是数字还是浮点值并转换为字符串。

    var obj1 = {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}};
    
    obj1.data.values.forEach(function(value, index, theArray) {
     if (!isNaN(value) || value.toString().indexOf('.') != -1)
        {
           theArray[index] = value.toString();
        }
    });
    
    console.log(obj1);

    【讨论】:

    • 感谢您的回答,但使用此方法会丢失大量数据。
    • Javascript 不支持大数字,因为它们会截断它们,因此要保留它们,您需要将它们作为字符串从服务器本身发送
    • 是的,我知道,这就是我问这个问题的原因。但是我不能更改服务器,这是特定设备上的服务器,不能那样更改。
    【解决方案3】:

    如果你真的需要通过正则表达式来做,那么你可以试试这个。

    const regex = /(-?\d+(\.\d+)?)(?![^,]*")/g;
    const str = `{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}`;
    const subst = `"$1"`;
    
    const result = str.replace(regex, subst);
    
    console.log(result);

    Regex Demo

    根据评论更新:

    (\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])
    

    Demo 2

    const regex = /(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])/g;
    const str = `{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,"test 123.3,2",0,"test 123.32",0,0,"","adsa22s22",0]}}`;
    const subst = `$1"$2"`;
    
    
    const result = str.replace(regex, subst);
    
    console.log(result);

    【讨论】:

    • 我认为这不适用于原始测试数据中的 "test 123.32" 示例。
    • 再问一个问题,如果我有 ","adsa22s22"," 它也会匹配 2,我该如何逃避它们的匹配?
    • @MilenGrigorov 现在能回答你的问题了吗?
    • 我不能谈论 OP 的要求,但像 "test 123.32, 16" 这样的东西很难使用 RegExp 正确处理。
    • 哦 @skirtle 刚刚举了一个很好的例子,现在我想知道是否有可能抓住每一个案例。
    【解决方案4】:

    如果您确实无法更改原始 JSON 以使用字符串表示不在 JS 支持的范围内的数字,那么您可以使用以下内容:

    var json = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0, "test \\u0022 123", "test \\" 123"]}}';
    
    var inString = false;
    var inNumber = false;
    var out = '';
    
    for (var index = 0, len = json.length ; index < len ; ++index) {
        var chr = json.charAt(index);
        
        switch (chr) {
            case '"':
                inString = !inString;
                break;
                
            case '\\':
                out += chr + json.charAt(index + 1);
                ++index;
                continue;
                
            case '-':
            case '.':
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
                if (!inString && !inNumber) {
                    out += '"';
                    inNumber = true;
                }
                
                break;
                
            default:
                if (inNumber) {
                    inNumber = false;
                    out += '"';
                }
        }
        
        out += chr;
    }
    
    console.log(out);

    使用 RegExp 处理字符串中的数字太棘手了,所以我什至没有尝试过。我假设 JSON 是有效的......如果不是,我的粗略解析器将无法很好地处理。我也忽略了数字的7e5 符号,这需要一些额外的工作来避免匹配true 中的e

    我没有明确地针对数组values,但可以对其进行相应调整。具体如何做取决于您是要处理通用 JSON 还是更针对您的确切格式的东西。例如,您可能只在数字达到一定长度时才在数字周围加上引号。通过跟踪数字开始的确切索引而不是仅使用isNumber 标志,这将很容易添加。

    如果我要在生产中使用这样的东西,我会编写大量单元测试以确保它确实有效。

    【讨论】:

      【解决方案5】:
      let obj = JSON.parse(response);
      obj.values = obj.values.map(item => typeof item === 'number' ? '"'+item+'"');
      console.log(JSON.stringify(obj));
      

      或使用 es5

      obj.values = obj.values.map(function(item) {
        return typeof item === 'number' ? '"'+item+'"';
      }
      

      或者代替 typeof item === 'number' 你可以使用 ! isNaN(项目)

      【讨论】:

      • 当我点击第一行“let obj = JSON.parse(response);”我丢失了大数字,因为 JS 不支持它们。无论如何,谢谢,上面的一些人给了我很好的正则表达式。
      【解决方案6】:

      先解析成JS对象

      var obj = JSON.parse( jsonString );
      

      然后

      obj.data.values = obj.data.values.map( function( item ){ return !isNaN( item ) ? String( item ) : item; });
      

      将其转换回 JSON 字符串格式

      jsonString  = JSON.stringify( obj );
      

      但是,如果数字超出了 javascript 对象可以接受的范围,则使用此基于正则表达式的解决方案

      var str = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}';
      
      str = str.replace(/[,|\[](\-){0,1}\d+(\.\d+)*(?=[,|\]])/g, function(match){ var firstChar = match.charAt(0); match = match.substring( 1 ); return firstChar + "\"" + match + "\"" ; });
      
      console.log( str );

      【讨论】:

      • 我正在转换它们,因为我需要处理 JS 不支持的大数字,我只需要获取这些值并将它们放在页面上。大数字是这样的:9223372036854775807。试着把它像一个数字一样放在你的控制台上。如果有更好的方法可以做到这一点,我会很乐意使用它,但我不知道。所以我将它们转换为字符串,然后用 JSON 解析器解析它们。
      • @MilenGrigorov 我现在明白了,解析为 json/number 方法不起作用。
      • 现在很好用,谢谢,但我已经接受了 Rizwan Tuman 的回答。
      猜你喜欢
      • 2021-10-17
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 2017-04-15
      • 2011-05-11
      • 1970-01-01
      • 2022-12-03
      相关资源
      最近更新 更多