PCRE de várias linhas com lookhead, count matches

2

Estou tentando executar um regex que corresponda se a palavra cat AND dog estiver no regex com suporte a várias linhas

matches

cat asdjfaldsfj dog
####
does NOT match

cat adfasdf8989
####
matches

dog adlsjf88989 cat
####
matches

cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf

O regex que estou usando é bastante simples

/^(?=.*\bcat\b)(?=.*\bdog\b).*$/gs

O problema é que isso só encontra a primeira ocorrência porque é gananciosa. Eu realmente quero o seguinte para contar dois jogos, mas só coincide uma vez

cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf
cat asdf8a89sdf8
a sdf asd f ads f ads fasdf
dog  a dsf ads fads f
asdfadsfadsf

Mesmo sem o segundo conjunto de cães do STUFF, o regex ainda corresponde ao final.

    
por SquidZ00 14.09.2017 / 23:03

1 resposta

0

Algumas dicas, mas não uma resposta completa.

.* com /s vai comer tudo até o final da string. Mudando para o não-ganancioso .*? , porém, irá corresponder a uma string mínima; os lookaheads não são forçados para o jogo. Minha estratégia usual para lidar com isso é incluir âncoras no lookaheads, mas a combinação de várias linhas dificulta isso.

/m será necessário se você quiser corresponder várias vezes na mesma string e ainda usar ^$ anchors. Caso contrário, eles correspondem apenas ao começo e ao final da string.

A menos que você realmente precise de uma solução de caso geral, provavelmente vale a pena tentar um ordenando manualmente seus subpadrões, por exemplo:

(?gsmx)(?(DEFINE)
  (?<a>\bcat\b)
  (?<b>\bdog\b)
)
^.*?(?:
      (?&a).*?(?&b)|  # cat before dog
      (?&b).*?(?&a)   # dog before cat
    )[^\n]*
$

Existem algumas coisas realmente interessantes que você pode fazer com subpadrões recursivos e referências anteriores, mas eu não consegui estruturá-los em um caso geral para N lookaheads sem o número de etapas subindo rapidamente na faixa de 10k +.

    
por 15.09.2017 / 13:16