How to replace QRegExp in a string?

强颜欢笑 提交于 2019-12-10 10:34:24

问题


I have a string. For example:

QString myString = "Today is Tuesday";

The requirement is: when user types a string, if that string is contained in myString, then that part in the myString should be bold, and case insensitive (Qt::CaseInsensitive), but the format of myString should remain (upper case characters should be upper case and lower case characters should be lower case).

For example:

  • user types: tu -> Today is Tuesday
  • user types: ES -> Today is Tuesday
  • user types: aY -> Today is Tuesday

This is my function:

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 );
    }
  }
}

This function is wrong because

user types t -> today is tuesday.

What I need is Today is Tuesday

How should I update my function?


回答1:


We can use a different QString::replace(), which accepts a QRexExp, to substitute all occurrences. The key to this is that we need a capture group in order to replace the original text in the substitution, using a back-reference (\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>");
}

Demo

#include <QDebug>
int main()
{
    qInfo() << setBoldForMatching("THIS DAY (today) is Tuesday.", "Day");
}

THIS DAY (today) is Tuesday.




回答2:


Replacing a match with p_text will always change the case to the one of p_text. So you have to do the replacement step by step, like this:

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();
    }
}

As you can see, with this code, the start and stop tags will be inserted before and after the match, without changing the matched sub-string itself.

Here are some test cases:

  • Today is Tuesday + tu --> Today is Tuesday
  • Today is Tuesday + ES --> Today is Tuesday
  • Today is Tuesday + aY --> Today is Tuesday
  • Today is Tuesday + t --> Today is Tuesday

  • Today is today + To --> Today is today




回答3:


Solution

Change your setBoldForMatching like this:

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>");
    }
}

I have decided to keep the original content of myString, so the result is contained in str instead.

Example

I have prepared a small example for you in order to demonstrate the result. The full code is available on GitHub.

Result



来源:https://stackoverflow.com/questions/52054261/how-to-replace-qregexp-in-a-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!