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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Помогите составить регексп (или не регексп)  (Прочитано 5886 раз)
Alp
Гость
« : Сентябрь 25, 2009, 22:56 »

Надо произвольную html-строку побить на части используя следующее правило: строка должна быть побита по пробелам без оставления пустых кусков (три пробела подря не трактуются как пять пустых строк между ними), за исключением текста заключенного в тэги <a href="not important what here"></a>, который может содержать пробелы, но в итоговом списке должен быть одной строкой.

Пример:
- строка="Однажды в <a href="qweqwe">студеную зимнюю<a/> пору\nСижу <a href="zc">за решеткой в</a> темнице сырой"
- результат:
(
    ("Однажды", "в", "студеную зимнюю", "пору"),
    ("Сижу", "за решеткой в", "темнице", "сырой")
)

Я уже всю голову сломал пытаясь решить эту задачу красиво что с регекспами, что без них. Без них - и по пробелам бил, предварительно удалив все теги, а потом искал нужную последовательность (нет гарантии, что эта последовательность не появится в другом месте) и посимвольно проходился (совсем дурацкий способ с непонятны  кодом - не уверен, что сам его пойму через месяц). В обещем, умные идеи в голову не идут.
« Последнее редактирование: Сентябрь 28, 2009, 13:52 от alp » Записан
_OLEGator_
Гость
« Ответ #1 : Сентябрь 26, 2009, 00:19 »

Сначала заменить в строке все повторяющиеся пробелы, обрезать крайние пробелы и применить следующую функцию:
Код
C++ (Qt)
QRegExp reg("( |<a [^>]*>[^>]*</a>|\\n)");
int index = 0;
int oldIndex = 0;
QString text = Utf("Однажды в <a href=\"qweqwe\">студеную зимнюю</a> пору\nСижу <a href=\"zc\">за решеткой в</a> темнице сырой");
 
QList <QStringList> resList;
QStringList curList;
 
while ((index = reg.indexIn(text, index)) >= 0)
{
if (text.at(index) == '<')
{
oldIndex = index;
index += reg.matchedLength() + 1;
 
curList.append(text.mid(oldIndex, index - oldIndex - 1).replace(QRegExp("<[^>]*>"), ""));
}
else if (text.at(index) == '\n')
{
curList.append(text.mid(oldIndex, index - oldIndex));
resList.append(curList);
curList.clear();
index += reg.matchedLength();
}
else
{
curList.append(text.mid(oldIndex, index - oldIndex));
index += reg.matchedLength();
}
oldIndex = index;
}
curList.append(text.mid(oldIndex));
resList.append(curList);
 
Записан
zenden
Гость
« Ответ #2 : Сентябрь 26, 2009, 00:49 »

Код
C++ (Qt)
void splitHtml(QString text, QVector<QStringList> &result)
{
QString line;
text.remove(QRegExp("<([^>]*)>"));
foreach(line, text.split("\n"))
{
QStringList temp;
QRegExp rx("(\\S+)");
int pos=0;
 
while ((pos = rx.indexIn(line, pos)) != -1)
{
temp<<rx.cap(1);
pos += rx.matchedLength();
}
result<<temp;
}
}
 

Удаляем теги простейшим способом, ищем непробельные последовательности и на выходе в result получаем массив stringlist-ов
« Последнее редактирование: Сентябрь 26, 2009, 00:52 от zenden » Записан
Alp
Гость
« Ответ #3 : Сентябрь 26, 2009, 11:22 »

Удаляем теги простейшим способом, ищем непробельные последовательности и на выходе в result получаем массив stringlist-ов

Почти получилось, но не то - если внутри гиперлинка текст с пробелами, то он будет разделен на две строки в стринглисте. По условию - текст внутри гиперлинка должен быть сохранен как одна строка.
А разделение по пробелам я уже давно делал.
Записан
Alp
Гость
« Ответ #4 : Сентябрь 26, 2009, 11:24 »

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

Во! Это почти то, что надо! Спасибо! Она немного сломалась, если теги ссылки окружены еще тегами <nobr></nobr>, но с этим я уже сам разберусь. Спасибо.

А можешь немного пояснить что этот регексп из себя представляет?

"<a [^>]*>[^>]*</a>" - вот это я понимаю, соотвествует тому, что находится внутри гиперссылки включая теги, а вот зачем эта последовательность заключена в трубы, перед ней ищется пробел и в конце ищется "\n" - непонятно.
« Последнее редактирование: Сентябрь 26, 2009, 12:09 от alp » Записан
_OLEGator_
Гость
« Ответ #5 : Сентябрь 26, 2009, 12:22 »

Просто последовательно ищется первое вхождение символов "пробела", тегов <a>, либо символа перевода строки, вот такое регулярное выражение и получается:
( - пробел
| - или
<a [^>]*>[^>]*</a> - полностью выражение в гиперссылке
| - или
\\n - символ перевода строки
)

Как я понял из вопроса, надо побить по строкам, а потом по словам...
Записан
Alp
Гость
« Ответ #6 : Сентябрь 26, 2009, 12:37 »

Просто последовательно ищется первое вхождение символов "пробела", тегов <a>, либо символа перевода строки, вот такое регулярное выражение и получается:
( - пробел
| - или
<a [^>]*>[^>]*</a> - полностью выражение в гиперссылке
| - или
\\n - символ перевода строки
)

Как я понял из вопроса, надо побить по строкам, а потом по словам...

Ага, тогда ясно. Не могу сейчас понять вот чего - если, как я описал в ответе - гиперссылка заключена в теги <nobr>-</nobr> (что бы слова не переносились в случае наличия пробелов), тогда после текста в гиперссылке следующим элементов списка будет "/nobr>". А если просто удалить все nobr, тогда теряется символ перевода строки (если гиперрсылка в самом конце строчки, т.е. "\n" следуется сразу за тегом </a>).

Для случая "Однажды в студеную зимнюю <a href="qweqwe">пору<a/>\nСижу за решеткой <a href="zc">в темнице сырой</a>" начинаются проблемы - почему-то теряются все сиволы перевода строк и в результате получаем один список. Хотя регексп соответствует и переводу строки! Почему так?
Записан
_OLEGator_
Гость
« Ответ #7 : Сентябрь 26, 2009, 12:43 »

Не очень понятно какой случай имеется ввиду. Надо просто учеть в регулярном выражении такую ситуацию:
<nobr><a href="qweqwe">студеную зимнюю<a/></nobr>

или что то другое?
Поясни Улыбающийся
Записан
_OLEGator_
Гость
« Ответ #8 : Сентябрь 26, 2009, 18:59 »

Для случая "Однажды в студеную зимнюю <a href="qweqwe">пору<a/>\nСижу за решеткой <a href="zc">в темнице сырой</a>" ошибка в закрывающем теге <a/>

Измененная функция для обработки </a>\n:
Код
C++ (Qt)
QRegExp reg("( |<a[^>]*>[^>]*</a>|\\n)");
int index = 0;
int oldIndex = 0;
QString text = Utf("Однажды в студеную зимнюю <a href=\"qweqwe\">пору</a>\nСижу за решеткой <a href=\"zc\">в темнице сырой</a>");
 
QList <QStringList> resList;
QStringList curList;
 
while ((index = reg.indexIn(text, index)) >= 0)
{
if (text.at(index) == '<')
{
oldIndex = index;
index += reg.matchedLength();
curList.append(text.mid(oldIndex, index - oldIndex).replace(QRegExp("<[^>]*>"), ""));
if (text.at(index) == ' ') index ++;
}
else if (text.at(index) == '\n')
{
if (index != oldIndex) curList.append(text.mid(oldIndex, index - oldIndex));
resList.append(curList);
curList.clear();
index += reg.matchedLength();
}
else
{
curList.append(text.mid(oldIndex, index - oldIndex));
index += reg.matchedLength();
}
oldIndex = index;
}
 
if (oldIndex != text.length()) curList.append(text.mid(oldIndex));
resList.append(curList);
 
Записан
Alp
Гость
« Ответ #9 : Сентябрь 28, 2009, 12:13 »

Для случая "Однажды в студеную зимнюю <a href="qweqwe">пору<a/>\nСижу за решеткой <a href="zc">в темнице сырой</a>" ошибка в закрывающем теге <a/>

Измененная функция для обработки </a>\n:

Спасибо за помощь. Ошибка - это опечатка была, не более чем =) Проблема возникла в случае, когда символ конца строки следует непосредственно за закрывающим тегом гиперссылки. Тогда список не делился по \n.
Записан
Alp
Гость
« Ответ #10 : Сентябрь 28, 2009, 13:53 »

В итоге всё получилось. Я немного переписал функцию (в старом варианте ругалась на выход за пределы строки в одном из вызовов QString::at)
Код
C++ (Qt)
void splitHtml(QString text, QList<QStringList> &result)
{
   text = text.replace("<br/>", "\n");
   text = text.remove("<nobr>").remove("</nobr>");
 
   QRegExp reg("( |<a[^>]*>[^>]*</a>|\n)");
   QRegExp rxHLink("<[^>]*>");
 
   int left = 0, right = 0;
   QStringList lineList;
 
   while ( (right = reg.indexIn(text, left)) != -1 )
   {
       if(text.at(right) == '<')
       {
           right += reg.matchedLength();
           lineList << text.mid( left, right-left).replace(rxHLink, "");
           right--;
       }
       else if( text.at(right) == '\n' )
       {
           result << lineList;
           lineList.clear();
       }
       else
       {
           lineList << text.mid(left, right-left);
       }
 
       left = right+1;
   }
 
   result.append(lineList);
}
 
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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