【问题标题】:Tokenize string with space separated values unless values are wrapped in single quotes用空格分隔值标记字符串,除非值用单引号引起来
【发布时间】:2013-05-31 22:38:15
【问题描述】:

任何人都可以告诉我用不在单引号内的空格分割 java 脚本中的字符串。

如果字符串是

"0 60 120 180 '节点名称' 2 34 45 12"

然后它会这样标记

arr[0]=0 arr[1]=60 arr[2]=120 arr[3]=180 arr[4]='节点名称' arr[5]=2 arr[6]=34 arr[7]=45 arr[8]=12

在拆分期间,如果单引号被删除,那么也很好,因为这是图表中的图例名称,我必须在单个元素中获取该名称

【问题讨论】:

标签: javascript string split tokenize


【解决方案1】:

这个正则表达式会做到这一点:

var arr = string.match(/'[^']*'|[^ ]+/g) || [];

【讨论】:

    【解决方案2】:

    你可以这样做:

    var s = "0 60 120 180 'node name' 2 34 45 12";
    var arr = [];
    s.split("'").forEach(function(v,i){
        arr = arr.concat(i%2 ? v : v.trim().split(' '))
    });
    

    它还删除了单引号:

    ["0", "60", "120", "180", "node name", "2", "34", "45", "12"] 
    

    Demonstration

    【讨论】:

    • 请在 IE 8 上观看,在 IE 8 上的我的系统上这不起作用,但在 Firefox 上是可以的
    • 对于 IE8,你需要 forEach 的垫片,也许还需要 trim。由于您已经选择了答案,所以我不会写它们,但如果您愿意,可以在 MDN 中找到它们。
    【解决方案3】:

    如果您没有嵌套引号,这将起作用。首先我搜索字符串中的任何单引号,然后用space分割:

    var s = "0 60 120 180 'node name' 2 34 45 12";
    var a = s.split("'");
    var r = [];
    for (var i = 0, l = a.length; i <l; i++) {
        if (i % 2) {
            r.push("'" + a[i] + "'");
        }
        else {
            var x = a[i].split(' ');
            for (var j = 0, k = x.length; j < k; j++) {
                if (x[j] != '') {
                    r.push(x[j]);
                }
            }
        }
    }
    
    console.log(r);
    // ["0", "60", "120", "180", "'node name'", "2", "34", "45", "12"]
    

    【讨论】:

    • 我对 % 模数运算符有点粗略。您的 if 语句 if(i%2) 是否读取 - if(i\2) 是真的(有余数)做其他事情(如果它是假的)做其他事情(如果它完全除)
    • @MarkWalters 正确:if(i%2) 表示 if(i is not divisible by 2)
    • @JanDvorak 啊哈,谢谢。本质上使用%2 将对所有奇数返回true?
    • @MarkWalters 本质上,是的。更准确地说,它返回10(分别为真和假)。
    【解决方案4】:

    我想我可能有点晚了,而且有点冗长,但这是一个易于理解和通用的解决方案。适用于所有分隔符和“加入”字符。还支持长度超过两个单词的“加入”单词....例如“你好,我的名字是'jon delaware smith fred'我有一个'长名'”这样的列表......

    根据@Bergi 的建议,我已经让它变得不那么冗长了......

    function split(input, delimiter, joiner){
        var output = [];
        var joint = [];
        input.split(delimiter).forEach(function(element){
            if (joint.length > 0 && element.indexOf(joiner) === element.length - 1)
            {
                output.push(joint.join(delimiter) + delimiter + element);
                joint = [];
            }
            if (joint.length > 0 || element.indexOf(joiner) === 0)
            {
                joint.push(element);
            }
            if (joint.length === 0 && element.indexOf(joiner) !== element.length - 1)
            {
                output.push(element);
                joint = [];
            }
        });
        return output;
      }
    

    【讨论】:

    • “有点冗长”是一种轻描淡写的说法 :-) 如果您确实使用了一些标准数组方法,那就更好地理解了。
    • 我只使用了 split、length 和 push..... 然后 indexof 用于字符串。虽然有 2 个数组和 3 个 if,哈哈。我并不是说没有很多代码。我想如果我使用更多内置的东西,比如 concat 和 forEach.... 如果我有时间,我可能会编辑它。
    【解决方案5】:

    ES6 方案支持:

    • 除内引号外按空格分隔
    • 删除引号,但不删除反斜杠转义引号
    • 转义的引号变成引号
    • 可以在任何地方加上引号

    代码:

    string.match(/\\?.|^$/g).reduce((p, c) => {
            if(c === "'"){
                p.quote ^= 1;
            }else if(!p.quote && c === ' '){
                p.a.push('');
            }else{
                p.a[p.a.length-1] += c.replace(/\\(.)/,"$1");
            }
            return  p;
        }, {a: ['']}).a
    

    输出:

    [ '0', '60', '120', '180', 'node name', '2', '34', '45', '12' ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      • 2013-09-11
      • 2013-12-13
      • 2012-11-17
      • 2018-03-14
      • 2014-05-10
      相关资源
      最近更新 更多