Как заменить 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.

Результат

Скриншот

Другие вопросы по тегам