正则表达式查找每个出现的字符串,并且它后面必须始终跟有相同的字符串

Regex find every occurence of string and it must be always followed by the same string

我有一个字符串,它包含几个 "value=[something]" 部分。我需要编写一个正则表达式 (PCRE),只有当 "value" 始终具有相同的值时它才会成功。例如在字符串中 "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 之外的任何其他东西,即使它有一些自定义限制,例如我不能使用条件组。

不是纯粹的正则表达式解决方案,但可能用作解决方法

$ 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[[=12=]]++>1{exit 1}' 

通过使用 if 语句,您可以匹配此类输入字符串。这个想法是,如果第一组包含某些东西,它应该在使用 value= 字符串后匹配 </code> 中的相同值,否则(如果是第一次出现)它匹配并捕获等式的右侧作为第一组。 </p> <p>正则表达式:</p> <pre><code>^(?:(?!value).|value=(?(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
        (?!\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)(?!\S)|(\S++)))++$

这是一个解决方案(很长很丑)

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

解决方案的关键部分是重复三次的子表达式以进行陷印 value=:

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

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

比赛的核心是在 value= 的第一场比赛之后捕获 (\S+),然后在随后的比赛中使用该捕获作为 ()

Demo.

这对我有用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);