正则表达式找到每个字符串的出现,并且必须始终跟随相同的字符串

时间:2016-10-06 15:15:46

标签: regex pcre

我有一个字符串,它包含几个“value = [something]”部分。我需要编写一个正则表达式(PCRE),只有当“value”始终具有相同的值时才会成功。例如,字符串“value =”出现n次,如果值始终为“cat”,则成功,但如果找到“cat”以外的其他内容则失败。

我的尝试到目前为止写了一个正则表达式。我的方法是捕获“value =”的第一个值然后以某种方式匹配所有其他“value =”s,但我似乎无法找到一种工作方法。 当然我不知道它的价值是什么,这就是我必须抓住它的原因。

必须成功:

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之外我不能使用任何其他东西,甚至有一些自定义限制,例如我不能使用条件组。

4 个答案:

答案 0 :(得分: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}' 

答案 1 :(得分:1)

通过使用 if语句,您可以匹配此类输入字符串。这个想法是,如果第一组包含某些东西,它应该在消耗\1字符串之后匹配value=中的相同值,否则(如果是第一次出现)它匹配并捕获方程的右侧作为第一组。

正则表达式:

^(?:(?!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++)))++$

答案 2 :(得分: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(?!=))*$

解决方案的关键部分是重复三次子表达式以捕获value=

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

这允许我们放置^$锚点来捕获模式匹配部分之前或之后的无效输入。

匹配的核心是在(\S+)的第一场比赛后捕捉value=,然后在后续比赛中将该捕捉用作(\1)

Demo.

答案 3 :(得分: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);