Russian Qt Forum
Ноябрь 25, 2024, 23:53 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: regexp для одной простой задачи  (Прочитано 5675 раз)
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« : Май 30, 2011, 23:24 »

Приветствую)

Разбираюсь сейчас с регулярными выражениями. Хочу спросить совета.

Дело в следующем. Имеется текст вида (LaTeX):

... Note that the spectacular reentrant superconductivity predicted in 1997~\cite{Khusainov_97, Khusainov_97_PRB} has been recently observed experimentally in the Nb/CuNi bilayer~\cite{Zdravkov_06}...

Мне нужно составить список всех ссылок, что встречаются в тексте.
Ссылки (в данном текте их всего три: Khusainov_97, Khusainov_97_PRB, Zdravkov_06) находятся внутри команд \cite{...}. Причём их колличество (ссылок) не ограниченно, но не меньше одной и они разделяются запятыми.
Сама ссылка может содержать  цифры, нижнее подчёркивание, ну короче \w

Вот что-то не соображу, как написать одно рег. выражение, чтоб енто сотворить.

Сейчас я использую следующую (рабочую) схему:
Код
C++ (Qt)
   QRegExp rx("cite\\{([\\w\\s,]*)\\}"); /* Вытаскивает всё содержимое команды \cite{} */
   QRegExp rxAuthorRef("\\b(\\w+)\\b"); /* Из этого всего вытаскивает сами ссылки */
   QString str("Note that the spectacular reentrant superconductivity"
               "predicted in 1997~\cite{Khusainov_97, Khusainov_97_PRB}"
               "has been recently observed experimentally in the Nb/CuNi"
               "bilayer~\cite{Zdravkov_06}.");
 
   QStringList authorsRef; /* Список всех ссылок */
   int pos = 0;
   while (pos >= 0) {
       if ((pos = rx.indexIn(str, pos)) >= 0)  {
           QString s = rx.cap(1); /* s - содержит всё содержимое команды \cite{} */
           int pos2 = 0;
           while (pos2 >= 0) { /* В этом цикле извлекаем сами ссылки */
               if ((pos2 = rxAuthorRef.indexIn(s, pos2)) >= 0) {
                   QString author = rxAuthorRef.cap(1);
                   authorsRef.append(author); /* засовываем их в список */
                   pos2 += author.size();
               }
           }
           pos += s.size();
       }
   }
   authorsRef.removeDuplicates();
   qDebug() << authorsRef;
 
 

Этот вариант работает, но требует двух regexp'ов (и два цикла).
Хотелось бы реализовать это по-умному.
Как это сделать? В смысле, как написать один regexp, который всё бы это делал?
« Последнее редактирование: Май 30, 2011, 23:26 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Май 30, 2011, 23:45 »

Код
C++ (Qt)
QRegExp rx("\\\\cite\\{(.+)\\}");
QStringList authorsList;
int pos = 0;
while ((pos = rx.indexIn(str, pos)) != -1)
{
   authorsList << rx.cap(1).split(", ");
   pos += rx.matchedLength();
}
вроде так

и у тебя кстати в str бэкслэши не двойные Подмигивающий
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #2 : Май 30, 2011, 23:54 »

Код
C++ (Qt)
QRegExp rx("\\\\cite\\{(.+)\\}");
QStringList authorsList;
int pos = 0;
while ((pos = rx.indexIn(str, pos)) != -1)
{
   authorsList << rx.cap(1).split(", ");
   pos += rx.matchedLength();
}
вроде так

и у тебя кстати в str бэкслэши не двойные Подмигивающий
Спасибо. Правда это даёт несколько иной результат:
Код
C++ (Qt)
("Khusainov_97", "Khusainov_97_PRB}has been recently observed experimentally in the Nb/CuNibilayer~\cite{Zdravkov_06")
 
Вместо
Код
C++ (Qt)
("Khusainov_97", "Khusainov_97_PRB", "Zdravkov_06")
 
По-поводу не двойных бэкслэшей: я буду загружать файл (.tex) в котором все команды начинается с одинарного бэкслэша.
« Последнее редактирование: Май 30, 2011, 23:58 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #3 : Май 31, 2011, 00:05 »

а, значит надо использовать "нежадный" захват ".+?". как он тут пишется...
Код
C++ (Qt)
QRegExp rx("\\\\cite\\{(.+)\\}");
rx.setMinimal(true);
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
blood_shadow
Гость
« Ответ #4 : Май 31, 2011, 00:07 »

я бы использовал форвард референсес
можно усовершенствовать:
Код
C++ (Qt)
QRegExp rx("cite\\{[^\\}](?=\\})");
QStringList authorsList;
int pos = 0;
while ((pos = rx.indexIn(str, pos)) != -1)
{
   authorsList << rx.cap(1).split(", ");
   pos += rx.matchedLength();
}
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #5 : Май 31, 2011, 00:23 »

я бы использовал форвард референсес
можно усовершенствовать:
Код
C++ (Qt)
QRegExp rx("cite\\{[^\\}](?=\\})");
QStringList authorsList;
int pos = 0;
while ((pos = rx.indexIn(str, pos)) != -1)
{
   authorsList << rx.cap(1).split(", ");
   pos += rx.matchedLength();
}

Не работает  Грустный
Говорит - список пуст.
Да, забыл сказать, что между ссылками и между ссылкой и запятой и между {} может быть любое число пробелов. И соответственно список должен содержать ссылки без пробелов. Мелочь конечно, но эт ещё один цикл по списку...
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #6 : Май 31, 2011, 00:32 »

Не работает  Грустный
нежадный захват постом выше работает - проверено Подмигивающий
Да, забыл сказать, что между ссылками и между ссылкой и запятой и между {} может быть любое число пробелов. И соответственно список должен содержать ссылки без пробелов. Мелочь конечно, но эт ещё один цикл по списку...
да какой цикл Улыбающийся
Код
C++ (Qt)
authorsList << rx.cap(1).split(QRegExp(",\\s*"));
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #7 : Май 31, 2011, 00:42 »

Не работает  Грустный
нежадный захват постом выше работает - проверено Подмигивающий
Да, забыл сказать, что между ссылками и между ссылкой и запятой и между {} может быть любое число пробелов. И соответственно список должен содержать ссылки без пробелов. Мелочь конечно, но эт ещё один цикл по списку...
да какой цикл Улыбающийся
Код
C++ (Qt)
authorsList << rx.cap(1).split(QRegExp(",\\s*"));
Да, этот вариант работает)
Правда, если между первой { и последующей ссылкой идут пробелы то.. Грустный
В смысле если будет так: \cite{     Ref1,  Ref2}
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #8 : Май 31, 2011, 00:46 »

Цитировать
В смысле если будет так: \cite{     Ref1,  Ref2}
Понял.. Тогда нужно так:
Код
C++ (Qt)
QRegExp rx("cite\\{\\s*([^\\s].+)\\}");
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #9 : Май 31, 2011, 00:49 »

ну тогда придется еще trimmed() вызвать для первой строки в списке от split(). или твой вариант (вроде должен сработать).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #10 : Май 31, 2011, 01:02 »

Всем спасибо)
Пожалуй оставлю вариант kambala с дополнением
Код
C++ (Qt)
QRegExp rx("cite\\{\\s*([^\\s].+)\\}");
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.548 секунд. Запросов: 23.