假设我有一个JavaScript表达式作为字符串,如下所示:
string = ' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]'
现在我需要获取此表达式的某些部分,它们是"依赖关系" ,用于我正在做的事情。
这是我需要从该字符串中提取的内容
result = [
'collections.users[ currentUsers[ ids[1].id ] ]',
'currentUsers[ ids[1].id]', 'ids[1].id',
'users[ ids[1].id ]', 'ids[1].id'
]
它基本上需要每个"变量"其中有[*]
这是可能导致表达式发生变化的每个变量,我现在已经尝试这样做了大约3天,我到目前为止尝试过但失败的是
我试图将字符串拆分为"如果括号打开做某事",但是失败了。
我只是很难弄明白,我没有在代码中尝试过任何东西,因为我只是删除并重新开始。
< / LI> 醇>据我所知,这可能有点“本地化”#34;但是我已经在JavaScript聊天中询问了几天的建议并且没有任何地方可以获得,我没有别的选择。
任何人都有任何关于如何实现这一点的建议,请记住这个字符串不是静态的,可能有更深的条件吗?
有人为此建议过JSON,但我不知道这是怎么回事,您怎么看?
由于问题的性质,我会给予50+赏金最佳答案/建议
答案 0 :(得分:3)
您可能需要使用递归函数并迭代每个字符。每次你打开一个开括号,你输入一个新的递归层;每次你敲近一个括号,你都退出一个。
我相信这会给你你想要的东西。
var toParse = 'collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]';
var operators = ['&','|','+','-','=','/','*'];
var answer = [];
parseBrackets(0);
function parseBrackets(start) {
var openBrackets = 0;
var currentString = '';
for (var i = start; i < toParse.length; i++) {
if (toParse[i] == '[') { // open bracket
if (openBrackets == 0) {
parseBrackets(i + 1);
}
currentString += toParse[i];
openBrackets++;
} else if (toParse[i] == ']' && openBrackets-- == 0) { // close bracket
answer.push(currentString);
return;
} else if (operators.indexOf(toParse[i]) >= 0) { // this is an expression operator, don't include it
if (currentString != '') {
answer.push(currentString);
}
currentString = '';
} else { // add this character to the current string
currentString += toParse[i];
}
}
answer.push(currentString); // add the current string to the list of parsed 'dependencies'
}
console.log(answer);
这里是一个jsfiddle:http://jsfiddle.net/W87m3/5/
这是输出:
["1", " ids[1].id ", " currentUsers[ ids[1].id ] ", "collections.users[ currentUsers[ ids[1].id ] ] ", "1", " ids[1].id ", " users[ ids[1].id ]"]
答案 1 :(得分:1)
Regexp不适合这个问题,因为正则表达式无法“计数”。即无论你的正则表达式有多复杂,都会有一定程度的括号嵌套不被接受。
你真正需要的是一个解析器。有一些解析器生成器使用语法规则生成代码。以下是一些:Javascript parser generator。
您的规则看起来很简单。像这样:
Expression = AnythingExceptBrackets '[' Expression ']' AnythingExceptBrackets
| AnythingExceptBrackets
AnythingExceptBrackets = [^\\[\\]]+
当您获得生成器时,剩下的唯一步骤是将识别的标记粘贴到结果数组中。
答案 2 :(得分:1)
为了成功地解析短语,必须知道短语的完整结构。从给出的一个例子中确定所有可能的结构是不可能的。然而做出一些假设我已经使用Extended Backus-Naur Form(EBNF)定义了一个可能的结构。
假设每个数组元素可以具有整数,变量或其他数组元素作为索引,并且变量和数组元素可以具有使用点表示法编写的属性。数组元素列表可以在它们之间包含运算符。
然后,您可以根据需要更改和扩展此结构。
扩展Backus-Naur形式表示法
{} 0或更多
[] 1个或更多
()组
letter =&#34; a&#34; |&#34; b&#34; |&#34; c .....&#34; |&#34; x&#34; |&#34 ; Y&#34; |&#34; Z&#34; |&#34; A&#34; |&#34; B&#34; |&#34; .....&#34; |&#34 ; Y&#34; |&#34; Z&#34;
digit = 0&#34; |&#34; 1&#34; |&#34; 2&#34; |&#34; 3&#34; |&#34; 4&#34; |&#34; 5&#34; |&#34; 6&#34; |&#34; 7&#34; |&#34; 8&#34; |&#34; 9
整数= [数字]
term = [char | digit]
identifier =($ | _ | char){term}
property = .char {term}
variable = identifier {property}
指数=位数|变量|位
array = variable&#34; [&#34; index&#34;]&#34; {property}
operator =&#34;&amp;&amp;&#34; |&#34; ||&#34; | +&#34; |&#34; - &#34; |&#34; * &#34; |&#34; /&#34;
phrase = array {operator array}:
有fiddle解析短语并生成给定示例的结果
代码是
letter = /[a-zA-Z]/;
digit = /[0-9]/;
join = /[&|+\-*]/; //possible operators
var phrase=' collections.users[ currentUsers[ ids[1].id ] ] && users[ ids[1].id ]';
var ptr=0;
var stack=[];
phrase=phrase.replace(/\s/g,''); //remove extraneous white space
phrase+=':'; //add : as terminator
var crctr=readNext();
getArray();
document.getElementById('results').innerHTML=setResults();
function getArray() {
var L=new List();
L.name=getVariable();
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
if(crctr !=':') { //not end of phrase
if (join.test(crctr)) {
readJoin();
getArray();
}
}
}
function getIndex() {
var indx='';
if(crctr=="[") {
crctr=readNext();
if(digit.test(crctr))
{
indx=getInteger();
if(crctr==']') {
return indx;
}
}
else {
indx=getVariable();
if(crctr=="]"){
return indx;
}
else if(crctr=="[") {
var L=new List();
L.name=indx;
L.index=getIndex();
crctr=readNext();
if(crctr=='.') {
crctr=readNext();
L.property=getProperty();
}
stack.push(L);
return L;
}
}
}
else {
throw 'index error';
}
}
function getVariable() {
var v="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
v+=crctr;
crctr=readNext();
v+=getIdentifier();
if (crctr==".") {
v+=crctr;
crctr=readNext();
v+=getProperty();
}
return v;
}
else {
throw 'variable error';
}
}
function getIdentifier() {
var id="";
if(crctr=="$" || crctr=="_" || letter.test(crctr)) {
id=crctr;
crctr=readNext();
id+=getTerm();
return id;
}
else {
throw 'Identifier error';
}
}
function getTerm() {
var t="";
while(letter.test(crctr) || digit.test(crctr)) {
t+=crctr;
crctr=readNext();
}
return t;
}
function getProperty() {
var p='';
if(letter.test(crctr)) {
p=crctr;
crctr=readNext();
while(letter.test(crctr) || digit.test(crctr)) {
p+=crctr;
crctr=readNext();
}
if(crctr=='.') {
p+=crctr;
crctr=readNext();
p+=getProperty();
}
else {
return p;
}
}
else {
throw 'property error';
}
}
function getInteger() {
var i='';
while(digit.test(crctr)) {
i+=crctr;
crctr=readNext();
}
return i;
}
function readJoin() {
if(crctr=="&" || crctr=="|") {
crctr=readNext();
}
crctr=readNext();
}
function readNext(){
var crctr=phrase.charAt(ptr);
ptr+=1;
return crctr;
}
function List() {
this.name='';
this.index='';
this.property='';
}
function setResults() {
var r='results = [';
while(stack.length>1) {
var A=stack.pop();
r+='<br> '+listArrays(A)+',';
}
var A=stack.pop();
r+='<br> '+listArrays(A);
return r+='<br>]';
}
function listArrays(A) {
if(A.index.name) { //A.index is array
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+listArrays(A.index)+']'+prp;
}
else {
var name=A.name;
var indx=A.index;
var prp='';
if(A.property !='') {
prp='.'+A.property;
}
return A.name+'['+A.index+']'+prp;
}
}
这会将结果放在div <div id='results'></div>
代码需要对您拥有的其他示例进行测试。