【问题标题】:Javascript parse multiple brackets recursively from a string [duplicate]Javascript从字符串递归解析多个括号[重复]
【发布时间】:2021-06-28 10:02:30
【问题描述】:

我想解析以下字符串:

this OR (this AND (this OR (that AND this))) OR this

进入这个:

  [
    "this", 
    "OR", 
    [
      "this", 
      "AND", 
      [
        "this", 
        "OR", 
        [
          "that", 
          "AND",
          "this"
        ]
      ]
    ], 
    "OR", 
    "this"
  ]

但是,我还需要支持 "this is a text" OR this 之类的东西,它解析为 ["this is a text", "OR", "this"],其中引号代表整个字符串,它取消了单词之间的空格分隔。

但这不是问题,因为它不像括号那样递归,这可以通过 regex 来完成。

经过一番研究,这不能用 ES 正则表达式来完成,但可以用 PHP 的正则表达式来完成。 有没有办法用javascript的正则表达式来做到这一点?如果没有,最好的替代方法是什么,也许是为此的预建库?

【问题讨论】:

  • 你会如何使用 PHP 正则表达式(我不是 php 人)来做到这一点?因为理论上,如果表达式树的深度不受限制,正则表达式不能确保每个左括号都与正确的右括号匹配。你需要一个下推自动机。即使深度有限,正则表达式也会相当复杂。当然,各种语言中的正则表达式确实对纯正则表达式概念进行了一些扩展,它在计算机科学中是如何定义的......
  • @derpirscher 你好,对不起,我不是很清楚,我不是说递归,因为它不这样做。但它知道如何在不使用任何内括号的情况下找到自行闭合的括号:(\(([^()]|(?R))*\))。如您所见,它使用Subroutine token,其他语言不支持它。但是,如果您确实知道如何像 PHP 正则表达式但在 javascript 中解决此问题,那将解决我的所有问题,因为我可以递归地运行正则表达式
  • tsk tsk 用于在您的问题结束时潜入图书馆推荐请求。但是给你:见Parsing in JavaScript: Tools and Libraries
  • @Ben Beri, “但这不是问题,因为它不像括号那样递归,这可以用正则表达式来完成。” - 如何用正则表达式来完成?
  • @Nur 通过引号对所有值进行分组对于正则表达式来说是非常简单的任务,因为它不是递归的,不像括号中可以有 ( ( ( ) ) ) 之类的情况。我使用的引号正则表达式是(["'])(?:(?=(\\?))\2.)*?\1

标签: javascript regex string


【解决方案1】:

字符串只是一个字符流。

  • 首先我们需要一个词法分析器。它采用字符流并生成令牌。示例:
Input  = `"Hello world" (!)`
Output =  Lex(Input) -> ["Hello world", "(" , "!", ")"] 
  • 我们可以使用递归函数。我们可以在其中创建一个堆栈并返回新数组。
Tokens = ["Hello world", "(" , "!", ")"]
Result = [ "Hello world", ["!"] ]

let input = `this OR (this AND (this OR (that AND this))) "this is a text" OR this`

function* Lex(characters) {
    let token = "", char;
    while (char = characters.shift()) switch (char) {
        case '(': case ')':
            if (token) { yield token; token = '' }
            yield char
            break
        case '"':
            let index = characters.indexOf(char);
            token = characters.splice(0, index).join('');
        case ' ':
            if (token) yield token
            token = ''
            break
        default: token += char
    }
}
function fnName(tokens) {
    let result = [], item;
    while (item = tokens.shift()) {
        if (item == ')') return result
        result.push(item == '(' ? fnName(tokens) : item)
    }
    return result
}
let tokens = [...Lex(input.split(''))];
console.log(fnName(tokens))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2019-06-21
    • 2021-07-29
    • 2018-12-26
    相关资源
    最近更新 更多