Вытащить фамилии

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

Статус темы:
Закрыта.
Модераторы: xpert13
  1. BSunV

    BSunV

    Регистр.:
    8 окт 2008
    Сообщения:
    186
    Симпатии:
    45
    Помогите составить регулярку, а то моих познаний в этой области явно недостаточно.
    Есть текст:
    В основе этой фамилии одно из старых русских имен Агап (просторечное Агапей, старое Агопий), Агапион или Агапит, в переводе с греческого – ‘любить, любовь, любимый’. Имен этих сейчас почти уже не встретишь, однако от них и их производных (в частности, Ганя, Гаша, Агаша) образовались фамилии Агапеев, Агапьев, Агашков, Гапеев, Гашев.
    Возможно, в этот же ряд стоит поставить фамилии Агашин, Гашин (сын Агаши, Гаши), но велика вероятность образования этих фамилий от женского имени Агафья (в переводе с греческого – ‘добрая, хорошая’).

    Нужно составить регулярное выражение, позволяющее вытащить фамилии из текста.
    Я понимаю, что в данном случае невозможно составить выражение, которое будет вытаскивать только фамилии. Например в данном примере оно будет вытаскивать и имя Агафья (или я ошибаюсь?). Приемлем вариант, когда будет вытаскивать и имена и фамилии. Я потом буду чистить вручную.
     
  2. Sanuch

    Sanuch

    Регистр.:
    25 май 2009
    Сообщения:
    207
    Симпатии:
    70
    если вы пытаетесь парсить контент какого-то сайта, возможно стоит привязаться к его тегам?
     
  3. BSunV

    BSunV

    Регистр.:
    8 окт 2008
    Сообщения:
    186
    Симпатии:
    45
    Нет, это не парсинг контента сайта. Есть просто текстовый файл, из которого нужно вытащить фамилии.
     
  4. Sanuch

    Sanuch

    Регистр.:
    25 май 2009
    Сообщения:
    207
    Симпатии:
    70
    тогда пробуйте
    PHP:
    $reg '#([А-Я][а-я]+)#';
     
  5. tulvit

    tulvit Создатель

    Регистр.:
    26 янв 2010
    Сообщения:
    30
    Симпатии:
    5
    Если текста много, а потеря нескольких фамилий не критична, то можно сначала удалить первые слова в предложении или заменить у них прописную буквы на строчную, иначе они попадут в выборку вместе с именами/фамилиями.
    PHP:
    $reg "#\.[\s][А-Я][а-я]*#"
     
  6. BSunV

    BSunV

    Регистр.:
    8 окт 2008
    Сообщения:
    186
    Симпатии:
    45
    У меня такой пхп код:
    PHP:
    $fp=fopen("fam.txt""r");   //из этого файла читаем
    $name fopen("name.txt""w");   //сюда пишем результат

    while (!feof($fp))         //до конца файла  fam.txt
    {
    $order fgets($fp500);     //считываем одну строку

        
    if (ereg("([А-Я][а-я]+)"$order$regs))   //Результат, соответствующий регулярке сохраняется в массиве $regs

        
    {
         
    $temp $regs[0]."\r\n";   //Добавляем к каждому элементу перевод каретки на новую строку   
         
    fputs($name$temp);    //Результат пишем в name.txt
         
    }

    }
    fclose($fp);
    fclose($name);

    В результате работы скрипта в результирующем файле только два слова:
    Агап
    Возможно
    (в файле fam.txt находиться только абзац, который я привел в начале темы).
    Где ошибка?
     
  7. Sanuch

    Sanuch

    Регистр.:
    25 май 2009
    Сообщения:
    207
    Симпатии:
    70
    в приведеном вами тексте, сколько строк и сколько совпадений вы ищите в каждой строке?
     
  8. BSunV

    BSunV

    Регистр.:
    8 окт 2008
    Сообщения:
    186
    Симпатии:
    45
    ищу все совпадения,т.е.если попадается несколько фамилий, то должны вытащиться все. В данном случае должна вытаскивать все слова,начинающиеся с большой буквы. Понимаю что будет много мусора(в виде заглавных букв строки и имен), с этим буду бороться после того,как хоть в таком виде скрипт заработает. Т.е если кратко, то нужно вытащить все слова, начинающиеся с заглавной буквы.
     
  9. Sanuch

    Sanuch

    Регистр.:
    25 май 2009
    Сообщения:
    207
    Симпатии:
    70
    я задавал вопрос именно по вашей реализации и вашим входным параметрам. в примере из первого сообщения можно получить всего две строки, ereg, в свою очередь, сработал по принципу preg_match и вернул всего лишь один результат. Рекомендую заменить функцию ereg на preg_match_all.
     
    BSunV нравится это.
  10. BSunV

    BSunV

    Регистр.:
    8 окт 2008
    Сообщения:
    186
    Симпатии:
    45
    Заменил строчку
    if (ereg("([А-Я][а-я]+)", $order, $regs))
    на
    if (preg_match_all("([А-Я][а-я]+)", $order, $regs, PREG_SET_ORDER))
    и все заработало. Спасибо. И последний момент. В руководстве для по регуляркам для начинающих:
    Внутри функции, которая будет выполнять операцию со строкой при помощи вышеприведенного условия, совпадение будет запоминаться в специальных переменных, в PHP к ней можно обращаться через \1 в Perl - $1. В одном условии поиска может быть несколько инструкций запоминания: ([a-z]{5})([1-8]{4}) - проверит строку на совпадение с условием, в случае удачного совпадения, запомнит пять букв в \1 ($1), четыре цифры в \2 ($2). Если обратиться к переменной \0, то окажется, что в ней хранится вся совпавшая строка, которая была описана условием.

    как обращаться к этой переменной(?) \1 (меня интересует сам синтаксис). В книгах по рег.выражениям и пхп не нашел. Пробовал обращаться к ней по-разному - и как к переменной и как к массиву. не получается. спасибо
     
Статус темы:
Закрыта.