正则表达式(或其他建议)解析标签

时间:2010-11-17 16:12:35

标签: javascript regex parsing

我正在尝试解析从hashtag获取的字符串,到目前为止看起来像正则表达式可能是最干净的方法。该模式有一个解释,如下:

#p3                  -> p = 3
#h4                  ->         h = [ 4 ]
#h4,h6               ->         h = [ 4, 6 ]
#p3,h4,h6            -> p = 3,  h = [ 4, 6 ]
#h4,h6,p3            -> p = 3,  h = [ 4, 6 ]
#h4s2,6,10           ->         h = [ 4 ],    s = { "4": [ 2, 6, 10 ] }
#h4s2,6,10,h6s5      ->         h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5 ] }
#p20h4s2,6,10,h6s5,1 -> p = 20, h = [ 4, 6 ], s = { "4": [ 2, 6, 10 ] , "6": [ 5, 1 ] }

正如我所说,我认为正则表达式可能是我最好的选择,但它也是任何复杂的弱点。

如果您有其他建议/解决方案,那么我欢迎他们。我可以使用if/else和大量indexOf以及splits来执行此操作,等等......但我确信必须有更好的方法。

更新:左边的输出最好被视为解释。虽然这是期望的最终结果,但正则表达式解决方案不必解决完整问题,但可能让我参与其中。另外,重申一下,我正在使用 Javascript

3 个答案:

答案 0 :(得分:5)

您可以使用单个表达式来确定特定行是否有效,但如果您尝试基于输入字符串构建结构,那么您应该采用两步标记化/解析方案因为这会简化事情。

根据它的外观,您有三种类型的令牌:phs。每个标记都是一个字母,后跟一个数字(在s的情况下后跟更多的数字)。

所以我开始使用一个tokenizer,用于将字符串转换为一系列抽象标记。可以使用正则表达式匹配每个标记。

我们取这个字符串:#p20h4s2,6,10,h6s5,1。虽然仍有输入,但您将根据剩余输入创建一系列令牌。

您的第一个令牌是p,其值为20。然后,您有h,其值为4。然后是值s的{​​{1}},依此类推。要确定哪个令牌是哪个,请使用非常简单的正则表达式。 [2,6,10]的表达式可以是pp\d+可能是hh\d+看起来像s

标记化步骤的结果是一系列对象,如下所示:s(\d+)(,\d+)*。此时,您可以确定{ p(20), h(4), s(2,6,10), h(6), s(5,1) }s(2,6,10)的一部分,并构建您的结构,而不必担心结构的字符串表示。

现在,至于在JavaScript中实际实现它,它不会太难。令牌序列可以是一个数组,您可以使用if / else块和上面的正则表达式找到令牌。

重要的是分离你正在使用字符串表示的部分(标记化)和你正在使用抽象表示的部分(解析)。它使概念上的事情变得更加简单。如果您以后需要它们,也可以通过这种方式添加新类型的令牌。

答案 1 :(得分:2)

这是一些代码。

var p, h = [], s = {};

var re = /[ph][0-9]+|s[0-9,]*[0-9]/g;
var a;
while ((a = re.exec(myhashtag)) !== null) {
    var first = a[0].substring(0, 1);
    var rest = a[0].substring(1);
    if (first == 'p')
        p = parseInt(rest);
    else if (first == 'h')
        h.push(parseInt(rest));
    else {
        a = rest.split(',');
        for (var i = 0; i < a.length; i++)
            a[i] = parseInt(a[i]);
        s[h[h.length - 1]] = a;
    }
}

这仅使用正则表达式来查找看起来像p3h4s3,4,5的所有主题标签。其余的只是常规的JavaScript。

此代码非常 lax。如果hashtag中包含无法解析的垃圾,例如#p3_banana_*q4,则此代码只会忽略它。如果hashtag包含这样的废话,那么编写更严格的代码会抛出错误可能会更好。

答案 2 :(得分:0)

正则表达式用于确定给定模式是否存在,并且可能对其起作用(替换,移除等)。你想做更多的事情;你想确定一个模式是否存在,然后根据它进行某种解析。如果是我,我会按如下方式执行它(下面的伪代码):

if(string_begins_with('#')) {
    if(string_contains('p')) {
        // get numbers following using some "CSV-to-array" function
    }

    if(string_contains('h') {
        foreach('h') {
            // check for 's' following, do csv-to-array thing
        }
    }
}

编辑:如果你真的想走这条路,你将不得不使用前瞻。假设p在开头是固定的:

/
^\#
(p[\d,]+)?   # find the 'p'
(            # beginning of 'find the "h"' code
    h([[0-9],])  # find the 'h'
    (?=          # beginning of lookahead for 's'
        (s([[0-9],])+)?  # code for s, including a final ? since it may not 
                         # be there at all. I'm not sure if this part will work.
    )           # end of lookahead
)+            # end of code for 'h', + since you may have more than one 'h'
/

这可能需要一些工作,但这是一个开始。