2017-01-24 67 views
0

IM喜在JavaScript應用程序的工作,需要幫​​助搞清楚這個表達式的Javascript正則表達式難倒

我有一系列的字符串。他們是動態的,但確實有一套模式。

name eq 'abc' 
id in 'def' 
key | operator | value 

然後我有一個修改器「具有」

has name eq 'abc' 
!has id 
has address eq '123 sesame street' 
|modifier | key | operator | value 

我能提取修飾符和按鍵沒有問題,這個表達式

new RegExp(/(^(\s*!?has\s+)?([^\s]+)|(^\s*[^\s]+))/i) 

但問題來時,我有一個與修飾詞相同的鍵

has eq '123' 

以上的回報正則表達式「有EQ」在那裏我只需要「有」

has has eq '123' 

以上的回報適當「已經有」

有大量的運營商來處理的,但它們是一組值

任何幫助,將不勝感激

+1

你確定一個正則表達式是一個很好的模式?爲什麼不是簡單的解析器? –

+0

@DaveNewton我的應用程序比這裏看到的複雜得多。我還沒有找到符合我需要的東西。請提出建議!有很多我沒有看到。 –

+0

你可以在** eq **之前用'\ w +(?= \ s + eq \ b)'來挑出位嗎?當然,如果你有'eq'作爲操作符或修飾符名稱,這會受到類似的影響。 –

回答

1

輸入數據似乎遵循只有幾個可能的模式:

mod key 
    key op val 
mod key op val 

如果這是代表所有的數據,並且你信任你的輸入數據是良好的,一個簡單的快捷鍵是提取所有令牌,並通過提取的令牌的數量區分key op val模式與其他模式。

下面的演示展示的辦法,正確識別你的問題的測試用例:

function extract(str){ 
 
    var result = str.match(/'[^']*'|\S+/g); 
 
    if(result.length == 3){// key op val 
 
    return { 
 
     key: result[0], 
 
     op: result[1], 
 
     val: result[2] 
 
    } 
 
    } else {// mod key OR mod key op val 
 
    return { 
 
     mod: result[0], 
 
     key: result[1], 
 
     op: result[2], 
 
     val: result[3] 
 
    } 
 
    } 
 
} 
 

 
console.log(extract("!has id")); 
 
console.log(extract("has eq '123'")); 
 
console.log(extract("has has eq '123'"));

+0

你能夠修改這個假設值是一個自由文本字符串,可以包含空格嗎? –

+0

如果值是用引號引起來的,例如,演示代碼已經支持自由文本(除直接引用外的任何字符)。否則,你需要一個不同的方法。 –

+0

謝謝你我會測試! –

4

你需要特定的完全指定所有有效語法:

var keyval = '' 

keyval += "^\s*(\w+)\s+eq\s+'(.*)'$";  // for key eq 'val' 
keyval += "|^\s*has\s(\w+)\s+eq\s+'(.*)'$"; // for has key eq 'val' 

new RegExp(keyval, 'i'); 

我不知道,如果你需要的has var!has var線沒有價值,如果你做,你可以添加:

keyval += "|^\s*!?has\s+(\w+)$"; // for has key and !has key 

需要注意的是與你的正則表達式的主要問題是沒有認識到eq是一個重要的關鍵詞。


其他注意事項:

個人而言,我不會用一個正則表達式這一點。這樣做會使得正則表達式冗長複雜,並且也會使提取匹配變得困難。你可以使用上面的技巧分解一個長的正則表達式,但在我看來,使用許多較小的正則表達式更好。我會寫如下內容:

var key_equal_pattern  = /^\s*(\w+)\s+eq\s+'(.*)'$/i; 
var has_key_equal_pattern = /^\s*has\s(\w+)\s+eq\s+'(.*)'$/i; 
var has_patten   = /^\s*!?has\s+(\w+)$/i; 

if ((m = input.match(key_equal_pattern)) !== null) { 
    // handle match 
} 
else if ((m = input.match(has_key_equal_pattern)) !== null) { 
    // handle match 
} 
else if ((m = input.match(has_patten)) !== null) { 
    // handle match 
} 

與巨大的正則表達式相比,這更易於維護。請注意,雖然常見的說法是你不能用正則表達式來解析html之類的東西,但人們真正想說的是,你不能用一個正則表達式來完成它。幾乎所有的html解析器都在標記化過程中使用regexp,然後使用iffor循環來處理數據的結構。

+0

是的,這真的讓我覺得!這是一個好方法。我今晚將應用這個想法並更新我的研究結果 –