2016-10-06 16 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); 
相关问题