【问题标题】:Regex (or other suggestion) to Parse a Hashtag正则表达式(或其他建议)来解析 Hashtag
【发布时间】:2011-05-11 12:37:21
【问题描述】:

我正在尝试解析从主题标签中获得的字符串,到目前为止,看起来正则表达式 可能 是最干净的方法。模式,带解释,如下:

#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 和很多indexOfsplits 等等来做到这一点......但我确信一定有比这更好的方法。

更新:左边的输出最好被认为是一种解释。虽然这是理想的最终结果,但正则表达式解决方案不必解决全部问题,但也许可以让我参与其中。另外,重申一下,我正在使用 Javascript

【问题讨论】:

  • 您可以发布常规模式吗?喜欢模式的概括?
  • @jjnguy:听上去如果他能做到,他就不需要问这个问题了。
  • @Welbog,我希望他能自己回答这个问题。
  • 我什至不知道如何在不发布答案的情况下提出这个问题。
  • @jjnguy @Welbog 说了什么......现在我有一些不工作、非基于正则表达式的复杂代码。将它包含在此处会更令人困惑而不是有帮助。

标签: javascript regex parsing


【解决方案1】:

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

从外观上看,您拥有三种类型的令牌:phs。每个令牌都是一个字母,后跟一个数字(在s 的情况下,后跟更多数字)。

所以我会从一个标记器开始,旨在将字符串转换为一系列抽象标记。每个标记都可以使用正则表达式进行匹配。

让我们使用这个字符串:#p20h4s2,6,10,h6s5,1。虽然仍有剩余输入,但您将根据剩余输入创建一个标记序列。

您的第一个令牌是p,其值为20。然后你有一个h,其值为4。然后是一个s,其值为[2,6,10],以此类推。要确定哪个标记是哪个,请使用一个非常简单的正则表达式。 p 的表达式可以是 p\d+h 可能是 h\d+s 看起来应该是 s(\d+)(,\d+)*

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

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

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

【讨论】:

    【解决方案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。

    此代码非常松懈。如果主题标签中包含无法解析的垃圾,例如#p3_banana_*q4,则此代码将忽略它。如果主题标签包含此类废话,最好编写更严格的代码以引发错误。

    【讨论】:

    • 这正是我的想法。
    • 谢谢。还没有完成所有的测试用例,但它到目前为止工作......并且比我以前的更优雅。
    • 如果 's' 只有一个值,它会被忽略,但对正则表达式的一个小修改可以解决:var re = /[ph][0-9]+|s[ 0-9,]+|[0-9]/g;
    • @michael 哎呀,你是对的。我将+ 更改为*,我认为它现在应该可以更好地工作了。
    【解决方案3】:

    正则表达式用于确定给定模式是否存在,并可能对其进行操作(替换、删除等)。你想做的不止于此;您想确定是否存在模式,然后基于此进行某种解析。如果是我,我会执行如下(伪代码如下):

    if(string_begins_with('#')) { 如果(字符串包含('p')){ // 使用一些“CSV-to-array”函数获取数字 } if(string_contains('h') { foreach('h') { // 检查 's' 跟随,做 csv-to-array 的事情 } } }

    编辑:如果你真的想走这条路,你将不得不使用前瞻。假设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'
    /
    

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

    【讨论】:

    • 我已经走上了这条路,这可能是我唯一的选择。我希望正则表达式至少可以部分分解它。旁注:我使用的是 Javascript,而不是 PHP
    猜你喜欢
    • 2023-03-24
    • 2010-12-06
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多