【问题标题】:Regex to split string into separate keys正则表达式将字符串拆分为单独的键
【发布时间】:2011-12-07 03:23:47
【问题描述】:

从事一个有趣的项目,我在为此编写正则表达式时遇到了一些麻烦。

使用正则表达式和 Javascript,我想将输入字符串拆分为“键”数组。具有无效键的字符串应返回 0 个键(null、空数组,任何都可以)。

“规范”

<input string>      => <matches>

# named keys
a                   => ['a']
b                   => ['b']
foo[bar]            => ['foo', 'bar']

# numeric keys are ok too
a[0]                => ['a', '0']
b[1]                => ['b', '1']

# 'push' syntax is also valid
push[]              => ['push', '']
hello[]             => ['hello', '']

# complex!
complex[named][0][] => ['complex', 'named', '0', '']

无效示例

# named keys must start with [a-zA-Z]
_invalid            => null
3foo[abc]           => null

# named keys can include a number as long as they start with a letter
foo3valid[this_is_valid_2] => ['foo3valid', 'this_is_valid_2']

到目前为止我所拥有的

var regex = /^(?:\[?([a-zA-Z][a-zA-Z0-9_]*|[a-zA-Z0-9_]*)\]?)+$/g;
var keys = [];

myInput.replace(regex, function(match,capture,pos,source){
    keys.push(capture);
});

console.log(myInput, keys);

如何失败

我的正则表达式只匹配最后一个“键”,例如,

# should be ['a', 'b', 'c']
a[b][c]   => ['c']

在 jsFiddle 上的修补程序

jsfiddle

【问题讨论】:

  • 我得到 ['c'] 与你的正则表达式反对 'a[b][c]'。
  • @MikePartridge 我添加了一个 jsFiddle 链接。 jsfiddle.net/MVJZc
  • @MikePartridge,我在不同的测试中得到了假阳性结果。你是对的,上面的正则表达式只捕获最后一个键。 (我更新了问题)

标签: javascript regex


【解决方案1】:

我采取了另一种方法来获得预期的结果:

  1. 测试给定的短语是否有效。
  2. 如果有效,则使用全局匹配来创建数组。

代码:小提琴:http://jsfiddle.net/MVJZc/2/

///Example
var myInput = "a[b][][c]";

var validate = /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
    pattern = /[a-zA-Z0-9_]+|(?=\[\])/g,
    //(?=\[\]) is used to create an empty entry for []
    keys = null;
if (validate.test(myInput)) {
    keys = myInput.match(pattern);
}

注意:如果你想扩展模式,例如要包含 $ 字符,请修改第一个 RegEx。第二个 RegEx (pattern) 至少应包含所有有效字符。

【讨论】:

  • 这已经接近了,但有些输入没有通过。在此处查看结果:jsfiddle.net/MVJZc/3
  • @macek 用我的小提琴。我的第一个答案(你用过你的小提琴)在validate 模式中缺少+ 符号。 jsfiddle.net/MVJZc/2
  • 顺便说一句,如果[...] 只能以数字开头,则使用/^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z][a-zA-Z0-9_]+)\])*$/,如果它仅由数字组成,或者/^[a-zA-Z][a-zA-Z0-9_]*(?:\[[a-zA-Z0-9_]+\])*$/,如果b[3ab] 也有效。
【解决方案2】:

这样的东西会起作用吗?

var input = "a[b][c]";
input = input.replace(/[\[\]]$/,"").replace(/[\]\[]+/g,"|");
var args = input.split("|");

这是一个演示: http://jsfiddle.net/vZBtj/

【讨论】:

  • 这不会验证每个密钥。它只验证第一个。例如,foo[_invalid]foo[bar][ fails2] 不应返回密钥。
  • @macek 我明白了...我会回去修复它,但您似乎已经找到了答案。 :P
【解决方案3】:

这是另一种可能性,绝对不像 Rob W 那样简洁,但可以完成工作 ;-)

function parseThing(aStr){
    var res = [];
    success = false;
    if(aStr.indexOf('[') > 0){
        var idx = aStr.indexOf('[');
        var first = aStr.substring(0, idx);
        if(first.match(/\w/)){
            success = true;
            res.push(first);

            //now parse stuff inside brackets
            var rest = aStr.substring(idx, aStr.length-1);
            var arr = rest.split("]");
            for(i in arr){
                res.push(arr[i].replace("[", ""));
            }
        }
    } else if(aStr.match(/\w/)){
        res.push(aStr);
    }
    return res;
}

console.log(parseThing("a[a][b]"));
console.log(parseThing("a"));
console.log(parseThing("b"));
console.log(parseThing("foo[bar] "));
console.log(parseThing("a[0]"));
console.log(parseThing("b[1]"));
console.log(parseThing("complex[named][0][]"));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多