Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > Помогите плиз с регулярным выражением


Автор: Konstantin555 19.8.2008, 14:19
Есть файл следующего содержания:
Код

=N=A=M=E= Name_1 =N=A=M=E=
<Name_11>

***Chapter_1***
Some text 1 Some text 2 Some text 3 Some text 4 
Some text 5 Some text 6 Some text 7 Some text 8 

***Chapter_2***
Some text 9 Some text 10 
Some text 11 Some text 12 
Some text 13 Some text 14 
Some text 15 Some text 16 
Some text 17 Some text 18 
***End_chapter***



Нужно определить текст, идущий между ***Chapter_1*** и ***Chapter_2***, а также ***Chapter_2*** и ***End_chapter***

Пробывал следующим образом - результат нулевой...
Код

<?php
 $cur=file_get_contents("Sample.txt");

 function get_short_new_reg($TxtFile)
 {
  $pattern="/(\\*[3]\w\W\w\\*[3]\s)/im";
  $a=preg_match_all($pattern,$TxtFile,$res);
  $res_str="";
  for($i=0;$i<$a;$i++)
   $res_str.=$res[0][$i].' ';
  return $res_str;
 };

 echo "<form action='index_reg.php' method='POST'>";
 echo "<textarea name='m1' cols='50' rows='20'>".$cur."</textarea>";
 echo "<textarea name='m2' cols='50' rows='20'>".get_short_new_reg($cur)."</textarea>";
 echo "</form>";
?>


Насчёт паттерна:
Код

$pattern="/(\\*[3]\w\W\w\\*[3]\s)/im";

\*[3] - тройное повторение подряд знака *
\w - любая буква или цифра ("Chapter")
\W - не буква и не цифра ("_")
\w - любая буква или цифра ("1")
\*[3] - тройное повторение подряд знака *
\s - перевод на новую строку


Подскажите, плиз! В этом деле - я новичок! smile 

Автор: nornad 19.8.2008, 14:47
Цитата(Konstantin555 @  19.8.2008,  17:19 Найти цитируемый пост)
\*[3] - тройное повторение подряд знака *

уже неверно. "трйоное" - это {3}
ну и в целом паттерн неверен
Попробуй так:
Код

$pattern = '|\*\*\*.+?\*\*\*(.*?)\*\*\*.+?\*\*\*|';

должен выдавать весь текст между заголовками секций (заголовок в формате "***чаптер_17***"). Получать как $res[1][$i].

Добавлено через 2 минуты и 9 секунд
Но лично я бы тут не использовал регулярки. Секции идут последовательно и нетрудно их вытащить за один проход "ручками" по строке. Да и надёжнее. А регулярки - штука дорогая.

Автор: Konstantin555 19.8.2008, 14:59
Нет, не работает... Вот функция преобразованная:
Код

function get_short_new_reg($TxtFile)
 {
  $pattern = '|\*\*\*.+?\*\*\*(.*?)\*\*\*.+?\*\*\*|';
  $a=preg_match_all($pattern,$TxtFile,$res);
  $res_str="";
  for($i=0;$i<$a;$i++)
   $res_str.=$res[1][$i].' ';
  return $res_str;
 };


Цитата

Но лично я бы тут не использовал регулярки. Секции идут последовательно и нетрудно их вытащить за один проход "ручками" по строке. Да и надёжнее. А регулярки - штука дорогая.

Скорее всего так и придётся сделать...
В каком смысле "дорогая"? Капризная? smile 

Автор: nornad 19.8.2008, 15:50
Цитата(Konstantin555 @  19.8.2008,  17:59 Найти цитируемый пост)
В каком смысле "дорогая"? Капризная?

много времени и ресурсов.
попробуй такой вариант:
Код

$pattern = '/\*\*\*.+?\*\*\*((.|\n|\r)*?)\*\*\*.+?\*\*\*/';

а цикл я бы предложил делать foreach:
Код

foreach($res[1] as $str) { ... }

Автор: Konstantin555 19.8.2008, 16:54
Цитата(nornad @  19.8.2008,  15:50 Найти цитируемый пост)
Цитата(Konstantin555 @  19.8.2008,  17:59 )В каком смысле "дорогая"? Капризная?много времени и ресурсов.попробуй такой вариант:код PHP1:$pattern = '/\*\*\*.+?\*\*\*((.|\n|\r)*?)\*\*\*.+?\*\*\*/';highlightSyntax('php_M2Y4ZD','php');а цикл я бы предложил делать foreach:код PHP1:foreach($res[1] as $str) { ... }

Спасибо! Работает!


По поводу цикла foreach - как правильно передать параметры ему? Выдаётся предупреждение "Warning: Invalid argument supplied for foreach()", т.е. значение, присвоенное $TxtFile - не подходит
Код

 function get_chapter_text1($TxtFile)
 {
  foreach($TxtFile as $str)
  {
   echo $str.'<br>';
  };
 };



Код

foreach($res[1] as $str) { ... }

под $res[1] - что имеется в виду?

Автор: gta4kv 19.8.2008, 17:51
Ему массив надо передавать.
http://php.net/foreach

Автор: nornad 19.8.2008, 20:42
После preg_match_all в $res[1] и будет массив  smile 

Автор: Konstantin555 19.8.2008, 21:08
Цитата(nornad @ 19.8.2008,  20:42)
После preg_match_all в $res[1] и будет массив  smile

Бррр..... запутался!
Я так понял, что ты имел в виду следующее - вместо preg_match_all использовать цикл! Разве не так?..

Цитата

Но лично я бы тут не использовал регулярки. Секции идут последовательно и нетрудно их вытащить за один проход "ручками" по строке. Да и надёжнее. А регулярки - штука дорогая.

preg_match_all - как бы регулярка ведь... сам себе, на мой взгляд, противоречишь!

Автор: solenko 19.8.2008, 21:17
Konstantin555, считать файл в массив строк -- функция file
Далее в foreach построчно анализируете.

Автор: nornad 19.8.2008, 21:41
Цитата(Konstantin555 @  20.8.2008,  00:08 Найти цитируемый пост)
вместо preg_match_all использовать цикл! Разве не так?..

не так. foreach вместо for
А если без регулярки - это совсем по-другому будет  smile

Добавлено через 4 минуты и 55 секунд
Кстати, если интересен вариант без регулярок, то нужна новая тема - тут это офтопом будет.

Автор: Konstantin555 20.8.2008, 00:20
Цитата

Konstantin555, считать файл в массив строк -- функция file
Далее в foreach построчно анализируете.

Не получилось...

Цитата

Кстати, если интересен вариант без регулярок, то нужна новая тема - тут это офтопом будет.

Угу, интересует!

Тема http://forum.vingrad.ru/forum/topic-224987/kw-выборка-текста-выбор.html

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)