Как заменить QRegExp в строке?
У меня есть строка. Например:
QString myString = "Today is Tuesday";
Требование: когда пользователь вводит строку, если эта строка содержится в myString
то эта часть в myString
должно быть жирным шрифтом и без учета регистра (Qt::CaseInsensitive
), но формат myString
должен остаться (символы верхнего регистра должны быть заглавными, а символы нижнего регистра должны быть строчными).
Например:
- пользовательские типы:
tu
-> Сегодня вторник - пользовательские типы:
ES
Сегодняшний день - пользовательские типы:
aY
-> Тод ай - вторник ай
Это моя функция:
void myClass::setBoldForMatching( const QString &p_text )
{
QRegExp regExp( p_text, Qt::CaseInsensitive, QRegExp::RegExp );
if ( !p_text.isEmpty() )
{
if ( myString.contains( regExp ) )
{
myString = myString.replace( p_text, QString( "<b>" + p_text + "</b>" ), Qt::CaseInsensitive );
}
}
}
Эта функция неверна, потому что
типы пользователей t
-> Сегодня вторник.
То, что мне нужно, это сегодня вторник
Как мне обновить мою функцию?
3 ответа
Мы можем использовать другой QString::replace()
, который принимает QRexExp
, чтобы заменить все вхождения. Ключом к этому является то, что нам нужна группа захвата, чтобы заменить исходный текст в замене, используя обратную ссылку (\1
):
#include <QRegExp>
QString setBoldForMatching(QString haystack, const QString& needle)
{
if (needle.isEmpty()) return haystack;
const QRegExp re{"("+QRegExp::escape(needle)+")", Qt::CaseInsensitive};
return haystack.replace(re, "<b>\\1</b>");
}
демонстрация
#include <QDebug>
int main()
{
qInfo() << setBoldForMatching("THIS DAY (today) is Tuesday.", "Day");
}
ЭТОТ ДЕНЬ (сегодня) - вторник.
Замена матча на p_text
всегда будет менять регистр на один из p_text
, Таким образом, вы должны сделать замену шаг за шагом, как это:
void myClass::setBoldForMatching(const QString &p_text) {
QRegExp regExp( p_text, Qt::CaseInsensitive, QRegExp::FixedString );
QString start = "<b>";
QString stop = "</b>";
int i=-1;
while (-1 != (i=myString.indexOf(regExp,i+1))) {
myString.insert(i, start);
i += start.size();
i += p_text.size();
myString.insert(i, stop);
i += stop.size();
}
}
Как вы можете видеть, с этим кодом теги start и stop будут вставлены до и после совпадения, без изменения самой соответствующей подстроки.
Вот несколько тестов:
- Сегодня вторник +
tu
-> Сегодня вторник - Сегодня вторник +
ES
Сегодняшний день - Сегодня вторник +
aY
-> Тод ай - вторник ай Сегодня вторник +
t
-> Сегодня вторникСегодня сегодня +
To
-> Сегодня есть день
Решение
Измени свой setBoldForMatching
как это:
void myClass::setBoldForMatching(const QString &p_text)
{
QRegExp regExp(p_text, Qt::CaseInsensitive, QRegExp::RegExp);
QString str = myString;
if (p_text.isEmpty()) {
label->setText(myString);
return;
}
int count = 0;
int pos = 0;
QStringList matches;
while ((pos = regExp.indexIn(str, pos)) != -1) {
++count;
pos += regExp.matchedLength();
matches.append(regExp.capturedTexts());
}
foreach (const QString &match, matches) {
str.replace(match, "<b>" + match + "</b>");
}
}
Я решил сохранить оригинальное содержание myString
поэтому результат содержится в str
вместо.
пример
Я подготовил для вас небольшой пример, чтобы продемонстрировать результат. Полный код доступен на GitHub.