За последние 24 часа нас посетили 45860 программистов и 1807 роботов. Сейчас ищут 1665 программистов ...

Backreference в первом параметре - pattern функции preg_repl

Тема в разделе "Регулярные выражения", создана пользователем FiMka, 8 янв 2010.

  1. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Ребята, привет всем!

    Подскажите, пожалуйста, следующее:

    Текст для обработки:
    Вопрос: возможно ли использование backreference в первом аргументе pattern функции preg_replace() (http://ru2.php.net/manual/en/function.preg-replace.php)?

    Код (Text):
    1. $tmp = preg_replace("/\\t(.+?)\\{$1=(ADV|CONJ)\\b.+?\\}/i", "\t$1($2)", $input);
    Здесь bacreference $1 используется в первом параметре. На практике вижу, что, похоже, так нельзя. Так как в сети пока подтверждения не нашел, решил спросить у знатоков.
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    либо кавычки одинакрные поставь, либо пиши так
    \\1
     
  3. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Все равно не цепляет по регэкспу...

    Код (Text):
    1.  
    2. <?php
    3. if( isset( $_FILES["qwe"] ) ) {
    4.     $dictext = file_get_contents($_FILES["qwe"]["tmp_name"], FILE_TEXT);
    5.     if( ! empty($dictext) ) {
    6.         $tmp_ = $dictext;
    7.         $tmp_ = preg_replace('/(?<=\\t)(.+?)\\{.*?\\1=(A|ADV|CONJ)\\b[^{]+?\\}/', "$1($2)", $tmp_);
    8.         echo $tmp_;
    9.     }
    10. } else {
    11.     echo "Не указан файл!";
    12. }
    13. ?>
     
  4. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Код (Text):
    1. preg_replace("#(?<=\t|^)(.+?){(\\1(?:=(A|ADV|CONJ)=)?\|?)+}#","\\1(\\3)",$text);
     
  5. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Mr.M.I.T., спасибо за помощь! Но все же и этот вариант не прокатывает.
    Код (Text):
    1. if( isset( $_FILES["qwe"] ) ) {
    2.     $dictext = file_get_contents($_FILES["qwe"]["tmp_name"], FILE_TEXT);
    3.     if( ! empty($dictext) ) {
    4.         $text = "above{above}   поверх{поверх=ADV=|поверх=PR=}";
    5.         $text = preg_replace("#(?<=\t|^)(.+?){(\\1(?:=(A|ADV|CONJ)=)?\|?)+}#","\\1(\\3)", $text);
    6.         echo $text; // вывод: "above() поверх{поверх=ADV=|поверх=PR=}"
    7.     }
    Главное узнал, что bacreference возможен в pattern для preg_replace!

    Я вообще пользую конструктор RegexBuddy для отладки регулярных выражений (http://www.regexbuddy.com/), проверял в этот раз и другими конструкторами (напр. http://www.pcre.ru/eval/). Все работало согласно задумке, но в php какая-то заминка...
     
  6. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Похоже, что изначальная проблема с которой я начал описание в теме, связана с исходным файлом, загружаемым на парсинг. Если задаю текст для обработки в файле .php, то все ок, если загрузка из файла (пробовал и с utf-8 файлом и с ansi - результат тот же), скрипт не выводит ничего...
     
  7. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Если с файлом, то попробуй убрать вот это
     
  8. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Короче, не хочу забегать вперед, но, кажется, приближаюсь к разгадке. Загружаемый текстовый файл довольно крупный (~1,5 Мб) с большим количеством разнообразного текста. Похоже, preg_replace спотыкается на каком-то фрагменте в файле (возвращает NULL), в итоге скрипт выдавал пустышку. Сейчас урезал файл до первых нескольких строк - все нормально, пропарсилось! Осталось разобраться в чем же на самом деле была проблема. Как найду в чем было дело, опишусь :)

    Кстати, вопрос к знатокам: в каких случаях preg_replace может вернуть NULL?

    ru2.php.net отписались лишь вскользь:
     
  9. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Кажется вот:
    Блин...
     
  10. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
  11. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Ну у меня вообще-то pcre.recursion_limit и pcre.backtrack_limit были закомментированы в php.ini.
    Раскомментировал, поставил лимиты в 900 000, запустил скрипт, он подгрузил процессор на 50%, но так за минуту ни до чего и не додумался.
    В обрабатываемом файле знаков с пробелами: 897 243.
    Также напрягают вот такие комментарии:
    Мдаа.. непонятно чо делать. Наверное стоит кусками файлы читать.
     
  12. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Что я могу посоветовать. Простая регулярка кушает и 10мб файл при стандартном
    pcre.backtrack_limit = 100000

    Если тестируешь локально - то увеличивай на сколько сможешь. (10/20/100млн)
    только память выдели для PHP соответственно.

    Там не только число знаков в строке важно, а сколько вариантов конечных автоматов может построится строится как я понимаю.

    Т.е. для большого текста и скажем (.*)+ это число очень быстро растет в геометрической прогрессии.

    Попробуй переделать регулярку на более конкретный поиск.

    P.S. Настройки рекурсии, кстати пока лучше не трогай, ты только ухудшаешь себе задачу.
     
  13. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Согласен, большое спасибо за помощь!

    Да я бы рад уточнить, сам не люблю всяких .* .+ и прочего, одни проблемы начинаются, но в файле чего только нет. Видимо, придется кусками обрабатывать. Подумаю, конечно, еще, что можно уточнить в регулярке.

    Еще раз спасибо всем!
     
  14. FiMka

    FiMka Активный пользователь

    С нами с:
    12 май 2009
    Сообщения:
    66
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Короче, ребята, все получилось с Perl. С вышеуказанной регуляркой и текстовым файлом объема 1,5 Мб скрипт выполнился за менее чем три секунды!

    Вчера до трех утра сидел никак не мог скурить почему и в Perl не работает.
    Сегодня догадался - указал в явном виде кодировку и все!
    Код (Text):
    1. use locale;
    2. use POSIX;
    3. &POSIX::setlocale(&POSIX::LC_ALL, "Russian_Russia.866");