Javascript 匹配括号之间的内容

Javascript 匹配括号之间的内容,javascript,pattern-matching,Javascript,Pattern Matching,我的问题其实很简单:如何将字符串中外圆括号的内容与嵌套圆括号匹配,如下所示: Lorem (ipsum (dolor) sit) amet 我在很多情况下一直在努力解决这个问题,在我看来应该有一个非常简单的解决方案,因为相当多的语言使用基于树的结构(HTML/XML使用,JSON使用[[]]或{a:{}}) 这里的主要问题是,使用任何正则表达式,匹配都会在第一个右括号结束,而不是在正确的括号结束。我也曾考虑过使用String.split(“(”),甚至创建一个包含左括号和右括号索引的数组,但这

我的问题其实很简单:如何将字符串中外圆括号的内容与嵌套圆括号匹配,如下所示:

Lorem (ipsum (dolor) sit) amet
我在很多情况下一直在努力解决这个问题,在我看来应该有一个非常简单的解决方案,因为相当多的语言使用基于树的结构(HTML/XML使用
,JSON使用
[[]]
{a:{}}

这里的主要问题是,使用任何正则表达式,匹配都会在第一个右括号结束,而不是在正确的括号结束。我也曾考虑过使用
String.split(“(”)
,甚至创建一个包含左括号和右括号索引的数组,但这些方法最终也没有起到任何作用(也许我忽略了使用这些策略的方法)

到目前为止,我最好的尝试是检查每个字符,测试该字符是否为括号,然后继续,直到剩下0个打开的括号:

var str = 'Lorem (ipsum (dolor) sit) amet';
var opened = 1;
var start = str.indexOf('(')+1
for (var i=start; i<str.length && opened; i++) {
    if (str.charAt(i) == '(') opened++;
    else if (str.charAt(i) == ')') opened--;
}
console.log(str.substring(start, i-1));
var str='Lorem(ipsum(dolor)sit)amet';
var=1;
var start=str.indexOf(“(”)+1

对于(var i=start;i来说,根本的问题是正则表达式无法描述需要匹配括号的语言,因为这样的语言元素使语言上下文无关,这是一个经常被引用的例子,说明了下推自动机(PDA)与有限状态自动机(FA)相比,功能更强

最基本的,你想要的东西所需要的生产是

N = aNa
终端出现在非终端的两侧。这是上下文无关语法的签名示例,要求PDA识别它。与更简单的语法相反

N = aN
它表示正则表达式,只需要FA就可以识别它

您需要一个比正则表达式更强大的识别类。幸运的是,我可以推荐一个很好的javascript解析器生成器

好的,完成了,我是说“稍等一下”吗?我熟悉nodejs,所以这都是假设编写的。但是peg也支持浏览器中的操作,因为它都是javascript

你知道,经过这么长时间,我不太确定这是否是你想要的,但我已经这样做了,任何用至少一对括号包装的东西都会被保留下来,否则它就会被删除。我继续完成了这项工作,尽管这是一个大的ish项目,用于说明目的。但如果这不是你想要的,那么看看生成的解析树,它都是JSON

我已经将源代码存储在github GIST中,可以随意下载,或者其他任何东西

cat输入1
Lorem(ipsum(dolor)sit)amet
node match.js
如果您知道正好有一对外圆括号,有一种更快的方法:从左侧扫描字符串,直到遇到左圆括号(
strchr
);从右侧扫描,直到遇到右圆括号(
strrchr

三个好处:1)在扫描过程中,您仅针对单个字符值进行测试;2)您不必在括号内进行任何比较;3)有用于此目的的内置项


如果可以有几个外部对,您就无法避免扫描整个字符串并记录嵌套级别。

根据当前的答案,代码的简单性缺乏改进,除了必须下载一个相当大的库之外,我假设没有更简单的方法来做这件事。以下是易于使用的函数形式的代码:

function getMatchedBracket(str, pos) {
    pos = pos || 0;
    var opened = 1;
    var start = i = str.indexOf('(', pos)+1
    for (; i<str.length; i++) {
        if (str.charAt(i) === '(') ++opened;
        else if (str.charAt(i) === ')' && !--opened) break;
    }
    return str.substring(start, i);
}
//and to test it
console.log(getMatchedBracket('Lorem (ipsum (dolor) sit) amet')); //ipsum (dolor) sit
//If you find this doesn't work correctly for anything, please let me know.
函数getMatchedBracket(str,pos){
pos=pos | | 0;
var=1;
var start=i=str.indexOf(“(”,pos)+1

对于(;我该如何使用pegjs获取括号的内容呢?只要
parser.parse(str)[1]
还是什么?我想你可以在
的同时使用
loop@ManofSnow我的全部观点是,我的代码已经可以运行了,但我正在寻找一种更简单的方法来实现这一点。在这里,如果你的脚本能够与我的脚本匹配,那么它将以它应该的方式运行。按照你过去一直使用JU相同策略的尝试次数计算不要修改你的函数来解释单个的额外括号,我已经假设它不会工作,但是如果你认为你的方法可以工作,请尝试一下。我得到的印象是没有比我的方法更简单的方法了。
function getMatchedBracket(str, pos) {
    pos = pos || 0;
    var opened = 1;
    var start = i = str.indexOf('(', pos)+1
    for (; i<str.length; i++) {
        if (str.charAt(i) === '(') ++opened;
        else if (str.charAt(i) === ')' && !--opened) break;
    }
    return str.substring(start, i);
}
//and to test it
console.log(getMatchedBracket('Lorem (ipsum (dolor) sit) amet')); //ipsum (dolor) sit
//If you find this doesn't work correctly for anything, please let me know.