2016-10-06 15 views
3

我有一個字符串,它包含幾個「值= [something]」部分。我需要寫一個正則表達式(PCRE),只有當「值」始終具有相同的值時纔會成功。例如,在字符串「value =」中出現n次,並且如果該值始終爲「cat」,則成功,但如果發現「cat」以外的內容則失敗。正則表達式找到每個字符串的發生,它必須總是跟着相同的字符串

我到目前爲止嘗試失敗寫一個正則表達式。我的方法是捕獲「value =」的第一個值,然後以某種方式匹配所有其他「value =」,但我似乎無法找到工作方法。 當然,我不知道價值會是什麼,這就是爲什麼我必須捕捉它。

必須成功:

aaaaaaa bbbbb value=cat cccccc ddddd value=cat fffffff value=cat ggggg hh jjj value=cat kkkkk 

一定會失敗:

aaaaaaa bbbbb value=cat cccccc ddddd value=cat fffffff value=bat ggggg hh jjj value=cat kkkkk 

對不起,過於複雜的解釋。

編輯:可能我應該提到這一點,但我有限,我可以使用。在這個自定義環境中,除了PCRE之外,我不能使用其他任何東西,甚至有一些自定義限制,例如我不能使用條件組。

+0

你在哪裏使用正則表達式?可能是另一種方法? – chris85

+0

我在我們公司的一個工具的自定義環境中使用正則表達式,不幸的是限制適用...在系統中我想使用這個,我不能使用其他任何東西,只有(有限)PCRE。例如,我不能使用條件組。 :( – Tom

回答

1

更好地使用if語句可以匹配這樣的輸入字符串。這個想法是,如果第一組包含某些東西,它應該在使用value=字符串之後匹配\1中的相同值,否則(如果是第一次出現)它匹配並捕獲方程的右側作爲第一組。

正則表達式:

^(?:(?!value).|value=(?(1)\1(?!\S)|(\S++)))++$ 

注:如果多行應該作爲輸入傳遞,m修改應設置。

Live demo

說明:

^    # Assert beginning of line 
(?:    # Start of non-capturing group (a) 
    (?!value).  # If we are not hitting a `value=...` token, consume one character 
    |    # Else 
    value=   # Match `value=` 
    (?(1)   # If first capturing group is set 
     \1(?!\S)  # Next characters should be a back-reference to it 
     |    # Else 
     (\S++)   # Capture its value for the first time 
    )    # End of if conditional 
)++    # As much as possible (possessively) - non-empty line, end of non-capturing group (a) 
$    # Assert end of line 

如果value一部分是真實的或者類似的詞將被代替,像下面的一個做法是,幾乎快很多,說話高性能:

^(?:[^v\v]+(?!value).|value=(?(1)\1(?!\S)|(\S++)))++$ 
+0

這可能是最好的解決方案,如果我被允許在我們的環境中使用條件組(您的解決方案非常棒! – Tom

+0

我選擇了您的答案作爲解決方案,因爲這使我最接近於我最終創建的內容,就是這樣: – Tom

+1

^(?=。 +?value =(\ S {1,128})。+?value =)(?:(?! value =)。value = \ 1)+ $ – Tom

2

不是一個純粹的正則表達式的解決方案,但作爲一種解決方法

$ grep -oE 'value=\w+' pass | uniq | awk 'END{exit NR>1?1:0}'; echo $? 
0 

$ grep -oE 'value=\w+' fail | uniq | awk 'END{exit NR>1?1:0}'; echo $? 
1 

使用您的樣品輸入通可能是有用的和失敗的文件。

$ head pass fail 
==> pass <== 
aaaaaaa bbbbb value=cat cccccc ddddd value=cat fffffff value=cat ggggg hh jjj value=cat kkkkk 

==> fail <== 
aaaaaa bbbbb value=cat cccccc ddddd value=cat fffffff value=bat ggggg hh jjj value=cat kkkkk 

也許沒有uniq的

$ grep ... | awk 'a[$0]++>1{exit 1}' 
+0

嘿,謝謝,看起來像一個很好的解決方案,但不幸的是我只限於正則表達式(請參閱我對自己的帖子的評論) – Tom

1

這是一個解決方案(很長的難看)

^(?:[^v]|v(?!a)|va(?!l)|val(?!u)|valu(?!e)|value(?!=))*value=(\S+)((?:[^v]|v(?!a)|va(?!l)|val(?!u)|valu(?!e)|value(?!=))*value=(\1))*(?:[^v]|v(?!a)|va(?!l)|val(?!u)|valu(?!e)|value(?!=))*$ 

解決方案的關鍵部分是一個子表達式重複3次誘捕value=

(?:[^v]|v(?!a)|va(?!l)|val(?!u)|valu(?!e)|value(?!=)) 

這使我們能夠把^$錨點在模式匹配部分之前或之後捕獲無效輸入。

匹配的心臟是value=後的首場比賽捕捉(\S+),然後使用捕獲作爲(\1)在隨後的比賽。

Demo.

+0

醜陋,但到目前爲止,這似乎是唯一的解決方案實際上在我的環境中使用,我可能會這樣做,所以謝謝! – Tom

+0

看起來我不能使用這個醜陋但工作的解決方案,因爲重複次數在我們的系統中是有限的。可能我會想出一些東西我從你和雷沃的解決方案中瞭解到,我會檢查後來回來的結果! – Tom

+0

@Tom你可以將這與revo的解決方案結合起來,如下所示:'^(?:(?!value)。)* value =(\ S +)((?:(?!value)。)* value =(\ 1 ))*(?:(?!value)。)* $'([demo](https://regex101.com/r/YaeerH/2))。 – dasblinkenlight

0

這爲我工作的ES6fiddle.net。這不是很優雅,但它確實完成了工作。祝你好運!

let arr = "aaaaaaa bbbbb value=cat cccccc ddddd value=cat fffffff value=cat ggggg hh jjj value=cat kkkkk".toLowerCase().split(" ").sort(); 

function vKeeper(e,i,a){ 
    if(a[i].charAt(0) !== "v"){ 
     a[i] = ""; 
    } 
} 
function vStripper(e,i,a){ 
    a[i] = a[i].replace("value=",""); 
} 


arr.forEach(vKeeper); 

arr.forEach(vStripper); 


while(arr[0] === ""){ 
    arr.shift(); 
} 

var res = false; 

while(arr[0] === arr[arr.length-1]){ 

    if(arr.length === 1){ 

    res = true 
    break; 
    } else { 

     arr.pop() 
    } 
} 

console.log(res); 
相關問題