Uzun tekrarlanan dizeleri bulmak?

2 Cevap php

Ben acı uzun class, id, değişken ve fonksiyon isimleri ve tekrar alışması diğer kombine dizeleri ile bazı HTML / CSS / JavaScript var. Herhalde yeniden adlandırmak ya da birkaç tanesi yeniden ve yarım metni kesebilir.

Yani metinde uzun tekrarlanan dizeleri raporları basit bir algoritma için arıyorum. , Küresel adını eğer, en tasarruf doğuracak dizeleri vurgulamak için İdeal olarak, bu uzunluk çarpı örnekleri tarafından sıralama ters olurdu.

Bu, bazı zarif, 10 satır özyinelemeli regex var ki, ben kod 100 hatlarında acı yapabileceği bir şey gibi hissediyor. Ayrıca ödev sorunu gibi geliyor, ama değil sizi temin ederim.

PHP çalışır, ancak herhangi bir dilde bir şeyler görmeye dalabilir.

NOT: Ben HTML / CSS / JavaScript minification başına aramıyorum. Ben anlamlı metni gibi, bu yüzden elle yapmak istiyorum, ve şişkinlik karşı okunabilirliği tartın.

2 Cevap

Bu, tüm tekrarlanan dizeleri bulabilirsiniz:

(?=((.+)(?:.*?\2)+))

preg_match_all ile kullanan ve uzun birini seçin.

function len_cmp($match1,$match2) {
  return $match2[0] - $match1[0];
}

preg_match_all('/(?=((.+)(?:.*?\2)+))/s', $text, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
  $match[0] = substr_count($match[1], $match[2]) * strlen($match[2]);
}

usort($matches, "len_cmp");

foreach ($matches as $match) {
  echo "($matches[2]) $matches[1]\n";
}

Yinelenen dizeleri bir LOT orada olabilir gibi bu yöntem, ama oldukça yavaş olabilir. Bir asgari uzunluğu belirterek biraz azaltmak ve desen tekrar az sayıda olabilir.

(?=((.{3,})(?:.*?\2){2,}))

Bu üç (birinci + 2) en az üç yinelenen karakter sayısını ve tekrar sayısını sınırlayacaktır.

Edit: Changed to allow characters between the repetitions.
Edit: Changed sorting order to reflect best match.

Ben biraz geciktim görünüyor, ama aynı zamanda çalışır:

preg_match_all('/(id|class)+="([a-zA-Z0-9-_ ]+)"/', $html, $matches);

$result = explode(" ", implode(" ", $matches[2]));
$parsed = array();
foreach($result as $string) {
    if(isset($parsed[$string])) {
        $parsed[$string]++;
    } else {
        $parsed[$string] = 1;
    }
}
arsort($parsed);

foreach($parsed as $k => $v) {
    echo $k . " -> Found " . $v . " times<br/>";
}

Çıktıya gibi bir şey olacaktır:

some_id -> Found 2 times
some_class -> Found 2 times