2014-10-12 2 views
1

Я использую php для объединения текстового сервера в файл формата rtf. Мои поля идентифицируются последовательностью тильд в разных частях файла. Каждая последовательность имеет разную длину. Чтобы использовать substr_replace, чтобы заменить поле материалом слияния, мне нужно рассчитать длину последовательности тильд. я могу найти первую тильду без проблем с помощью:PHP нужно подсчитывать количество одинаковых символов в последовательности в строке

$firsttilde=strpos($filedata,'~',$currentposinfile); 

Где (в этом коде) $filedata это строка, содержащая содержимое файла и $currentposinfile мой начальная точка для поиска. Моя проблема в том, что я не могу найти функцию, которая может подсчитывать количество одинаковых символов в последовательности.

С первого тильды, что часть $filedata Я смотрю на внешний вид, как это (другими словами, последовательность тильды):

«~~~~~~~~~~»

Я пробовал strrpos, чтобы найти последнюю тильду, но это находит мои поля, содержащие тильды в более поздней части $filedata. Все, что я хочу сделать, это подсчитать количество тильд с позиции, о которой я знаю в строке, но я не могу найти какую-либо функцию для этого. Должен быть один, хотя.

+0

Таким образом, разница между положением первого тильды и позиция с первого символа не тильды с этой точки? – Sumurai8

ответ

0

Вы можете использовать preg_match_all в сочетании с флагом PREG_OFFSET_CAPTURE. Это сохранит смещение, при котором строка была найдена в переменной совпадений, что позволит вам найти строку и ее смещение.

$matches = Array(); 
preg_match_all('/~+/', $input, $matches, PREG_OFFSET_CAPTURE); 

foreach($matches[0] as $k => $v) { 
    $length = strlen($v[0]); 
    echo "Found a string \"{$v[0]}\" beginning at {$v[1]} with length {$length}<br>"; 
} 

Для примера ниже текст

$input = <<<TEXT 
this is 
~~~~~~~~ 

quite something 
~~~~ 
TEXT; 

выход будет:

Found a string "~~~~~~~~" beginning at 8 with length 8 
Found a string "~~~~" beginning at 34 with length 4 
0

Это использует для итерации для изучения символов в тексте. Это альтернатива решениям preg_match(), которые более компактны.

<?php 

$text = <<<'TEXT' 
abc 
~~~ 
def 
~~~~~~ 
123 
~~~~~~~~~~ 
TEXT; 

//$currentposinfile = 0; 
//$firsttilde = strpos($text,'~',$currentposinfile); 
//$text = substr($text, $firsttilde); 

$sequenceStarted = false; 
$sequenceLength = 0; 

$textLength = strlen($text); 

for ($i = 0; $i <= $textLength; $i++) { 
    $char = $text[$i]; 

    //echo 'Char ' . $char . ' at ' . $i . PHP_EOL; 

    if($char === '~') { 

     // found start of a sequence 
     if($sequenceStarted === false) { 
      $sequenceLength++;  
      $sequenceStarted = true;  
      $sequenceStartPosition = $i; 
     } 

     // it's a char in sequence    
     continue; 
    } 

    // found first char out of sequence 
    if($char !== '~' && $sequenceStarted === true) { 
     $sequenceStarted = false; 
     $sequenceEndPostion = $i - 1; 
     $sequenceLength = $i - $sequenceStartPosition; 

     echo 'Found a sequence of length: ' . $sequenceLength . ' starting at '.$sequenceStartPosition.' ending at ' . $sequenceEndPostion . '.' . PHP_EOL; 

     #break; 

     $sequenceLength = 0; $sequenceEndPostion = 0; 
    } 
} 

Результат:

Found a sequence of length: 3 starting at 5 ending at 7. 
Found a sequence of length: 6 starting at 15 ending at 20. 
Found a sequence of length: 10 starting at 28 ending at 37. 

Если у вас уже есть куски последовательности, вы можете просто использовать count_chars().

<?php 

$text = 'ABC~~~123'; 

$data = count_chars($text, 1); 

echo 'The string "'. $text .'" contains the char "~" '. $data[126] . ' times.'; 

$ данных [126] = использует код ASCII 126 для ~

Результат: Строка "ABC ~~~ 123" содержит символ "~" 3 раза.

Демонстрация: https://eval.in/204882

0

Следующая функция будет цикл через строку и возвращает массив совпадений:

function findSequences($str) 
{ 
    $ret = array(); 
    $len = strlen($str); 
    $count = 0; 

    for($i = 0; $i <= $len; $i ++) 
    { 
     $char = @$str[$i] ?: null; 

     if($char == '~') 
     { 
      $count ++; 
     } 
     elseif($count > 0) 
     { 
      // Found end of sequence 
      $ret[] = array(
       'start' => $i - $count, 
       'end' => $i - 1, 
       'len' => $count 
      ); 

      $count = 0; 
     } 
    } 

    return $ret; 
} 

Пример использования:

print_r(findSequences('~ABC~~~123~~')); 

будет выводить массив с деталями найдено совпадений:

Array 
(
    [0] => Array 
     (
      [start] => 0 
      [end] => 0 
      [len] => 1 
     ) 

    [1] => Array 
     (
      [start] => 4 
      [end] => 6 
      [len] => 3 
     ) 

    [2] => Array 
     (
      [start] => 10 
      [end] => 11 
      [len] => 2 
     ) 

) 
0

Спасибо всем за ваши ответы.
Они побудили меня попробовать немного сложнее найти простое решение.

Я пришел с этим: -

$lasttilde=$firsttilde; 
while ($filedata[$lasttilde]=='~') { $lasttilde++; } 

Тогда число тильды в этой конкретной части $filedata разница между $lasttilde и $firsttilde

Смежные вопросы