Pergunta

Eu tenho um conjunto completo de padrões que eu preciso combinados. Qualquer maneira de fazer isso, diferente de um para o (circular)? Eu estou tentando fazê-lo na forma intensiva menos CPU, já que vou estar fazendo dezenas destes a cada minuto.

exemplo do mundo real é, Im construção de um verificador de status do link, que irá verificar links para vários sites de vídeo online, para garantir que os vídeos ainda estão vivos. Cada domínio tem várias "palavras-chave mortas", se estes são encontrados no HTML de uma página, isso significa que o arquivo foi apagado. Estes são armazenados na matriz. Eu preciso para coincidir com o conteúdo pf a matriz, contra a saída HTML da página.

Foi útil?

Solução

Em primeiro lugar, se você literalmente apenas fazendo dezenas cada minutos , então eu não me preocuparia terrivelmente sobre o desempenho neste caso. Estes jogos são muito rápido, e eu não acho que você vai ter um problema de desempenho por iteração sua matriz padrões e chamando preg_match separadamente como esta:

$matches = false;
foreach ($pattern_array as $pattern)
{
  if (preg_match($pattern, $page))
  {
    $matches = true;
  } 
}

Você pode realmente combinar todos os padrões em um usando o operador or como algumas pessoas estão sugerindo, mas não basta colocá-las em conjunto com um |. Isso vai quebrar mal se qualquer um dos seus padrões contém o ou operador.

Eu recomendaria, pelo menos em agrupar os seus padrões usando parênteses como:

foreach ($patterns as $pattern)
{
  $grouped_patterns[] = "(" . $pattern . ")";
}
$master_pattern = implode($grouped_patterns, "|");

Mas ... Eu realmente não estou certo se isso acaba sendo mais rápido. Algo tem um loop através deles, se é o preg_match ou PHP. Se eu tivesse que adivinhar eu acho que os jogos individuais estaria perto de tão rápido e mais fácil de ler e manter.

Por último, se o desempenho é o que você está procurando aqui, eu acho que a coisa mais importante a fazer é puxar as partidas não regex em um simples "string contém" cheque. Imagino que algumas de suas verificações devem ser verificações de cordas simples como olhar para ver se "Este site é fechado" está na página.

Assim fazendo isso:

foreach ($strings_to_match as $string_to_match)
{
  if (strpos($page, $string_to_match) !== false))
  {
    // etc.
    break;
  }
}
foreach ($pattern_array as $pattern)
{
  if (preg_match($pattern, $page))
  {
    // etc.
    break;
  } 
}

e evitando como muitos preg_match() possível é provavelmente vai ser o seu melhor ganho. strpos() é um muito mais rápido do que preg_match().

Outras dicas

// assuming you have something like this
$patterns = array('a','b','\w');

// converts the array into a regex friendly or list
$patterns_flattened = implode('|', $patterns);

if ( preg_match('/'. $patterns_flattened .'/', $string, $matches) )
{
}

// PS: that's off the top of my head, I didn't check it in a code editor

Se os seus padrões não contêm muitos espaços em branco, outra opção seria a de evitar as matrizes e usar o modificador /x. Agora, sua lista de expressões regulares ficaria assim:

$regex = "/
pattern1|   # search for occurences of 'pattern1'
pa..ern2|   # wildcard search for occurences of 'pa..ern2'
pat[ ]tern| # search for 'pat tern', whitespace is escaped
mypat       # Note that the last pattern does NOT have a pipe char
/x";

Com o modificador /x, espaço em branco é completamente ignorado, exceto quando em uma classe de caracteres ou precedido por uma barra invertida. Comentários como acima também são permitidos.

Isso evitaria o loop através da matriz.

Se você está apenas procurando a presença de uma string em outra seqüência, uso strpos, pois é mais rápido.

Caso contrário, você poderia apenas iterar sobre o conjunto de padrões, chamando preg_match cada vez.

Se você tem um monte de padrões, o que você pode fazer é concatenar-los em uma única expressão regular e combinar isso. Não há necessidade de um loop.

Que tal fazer um str_replace() no HTML você se usando sua matriz e, em seguida, verificar se o HTML original é igual ao original? Isso seria muito rápido:

 $sites = array(
      'you_tube' => array('dead', 'moved'),
      ...
 );
 foreach ($sites as $site => $deadArray) {
     // get $html
     if ($html == str_replace($deadArray, '', $html)) { 
         // video is live
     }
 }

Você pode combinar todos os padrões da lista de expressão regular único usando implode () função php . Em seguida, teste a sua corda de uma vez usando preg_match () php função.

$patterns = array(
  'abc',
  '\d+h',
  '[abc]{6,8}\-\s*[xyz]{6,8}',
);

$master_pattern = '/(' . implode($patterns, ')|(') . ')/'

if(preg_match($master_pattern, $string_to_check))
{
  //do something
}

Claro que poderia ser ainda menos código usando implode () embutido no "if ()" condição em vez de variável $master_pattern.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top