Регулярные выражения в Qt реализованы классом QRegExp
. Рассмотрим основные варианты его использования на примерах.
В качестве примера рассмотрим регулярное выражение для проверки строки на точное соответствие директиве #include <…>
:
#include <QRegExp>
#include <QStringList>
#include <QDebug>
int main() {
QRegExp re( "#include <[^>]+>" );
QStringList strings = QStringList() <<
"#include <iostream>" <<
" #include <iostream> " <<
"#include \"iostream\"" <<
"#define <iostream>";
foreach( const QString& str, strings ) {
qDebug() << ( re.exactMatch( str ) ? "matched" : "mismatched" ) << ":" << str;
}
return 0;
}
В результате выполнения этого кода на консоли будет выведено (кроме комментариев, которые добавлены отдельно):
matched : "#include <iostream>" // Все правильно
mismatched : " #include <iostream> " // Лишние пробелы
mismatched : "#include "iostream"" // Вместо < использовано "
mismatched : "#define <iostream>" // Нам нужен include, а не define
Совпадение произошло лишь в первом случае, поскольку приведенное регулярное выражение учитывает только ТОЧНОЕ совпадение. Этот вариант использования регулярных выражений подойдет для проверки ip-адресов, MAC-адресов, адресов электронной почты и т.д.
Если вам нужно проверить не точное совпадение с регулярным выражением, а просто его наличие где-либо в строке, то воспользуйтесь функцией QString::contains()
, которая предназначена именно для этого.
Следующий пример демонстрирует способ поиска с помощью регулярных выражений всех упоминаний #include <…>
:
#include <QRegExp>
#include <QStringList>
#include <QDebug>
static const char* const TEXT =
"#include <QRegExp>\n"
"#include <QStringList>\n"
"#include <QDebug>\n"
"\n"
"int main() {\n"
"QRegExp re( \"#include <([^>]+)>\" );\n"
"int lastPos = 0;\n"
"while( ( lastPos = re.indexIn( TEXT, lastPos ) ) != -1 ) {\n"
"lastPos += re.matchedLength();\n"
"qDebug() << re.cap( 0 );\n"
"}\n"
"return 0;\n"
"}";
int main() {
QRegExp re( "#include <([^>]+)>" );
int lastPos = 0;
while( ( lastPos = re.indexIn( TEXT, lastPos ) ) != -1 ) {
lastPos += re.matchedLength();
qDebug() << re.cap( 0 ) << ":" << re.cap( 1 );
}
return 0;
}
Представленный выше код выведет следующее:
"#include <QRegExp>" : "QRegExp"
"#include <QStringList>" : "QStringList"
"#include <QDebug>" : "QDebug"
"#include <([^>" : "([^"
Обратите внимание, что под выбранное регулярное выражение подошли все упоминания #include
. Даже то, которое синтаксически является обычной строкой.
Также мы извлекли группу re.cap( 1 )
, содержащую текст внутри <…>
.
Аналогичным образом с помощью регулярных выражений вы можете искать в тексте номера телефонов; имена файлов и многое другое.
С помощью регулярных выражений удобно осуществлять замену фрагментов текста. Рассмотрим пример:
#include <QRegExp>
#include <QStringList>
#include <QDebug>
static const char* const TEXT =
"#include <QRegExp>\n"
"#include <QStringList>\n"
"#include <QDebug>\n"
"\n"
"int main() {\n"
"qDebug() << QString( TEXT ).replace( QRegExp( \"#include <([^>]+)>\" ), \"#include \"\\1\"\" );\n"
"return 0;\n"
"}";
int main() {
qDebug() << QString( TEXT ).replace( QRegExp( "#include <([^>]+)>" ), "#include \"\\1\"" );
return 0;
}
Записанное регулярное выражение меняет #include <…>
на #include "…"
. На консоль будет выведено следующее:
"#include "QRegExp"
#include "QStringList"
#include "QDebug"
int main() {
qDebug() << QString( TEXT ).replace( QRegExp( "#include "([^"]+)>" ), "#include "\1"" );
return 0;
}"
Такая замена осуществляется с помощью группы в регулярном выражении, обернутой в скобки. Ссылка на группу делается с помощью конструкции вида \\n
, где n
- номер группы, соответствующей индексу в вызове re.cap( n )
.
Этот прием хорошо подойдет для выполнения простых (и не очень) преобразований текста с помощью регулярных выражений, в которых легко выделяются группы.
Спасибо за комментарий. Думаю, что подобный материал и правда не помешало бы подготовить.
В строке
QRegExp re( "#include <[^>]+>" );
не понятно что за <[^>]+> - это маска какая то? Никогда не встречал подобного. Дайте ссылку на пояснение пожалуйста.
Здравствуйте. Выражение <[^>]+> ищет подстроки, которые начинаются с символа '<' и заканчивается символом '>', но не содержат символа '>' где-нибудь в середине ("[^>]+" - один или более символ, отличный от '>').
Например, в строке "<123><456>" есть два соответствия для <[^>]+>: "<123>" и "<456>", но одно соответствие "<123><456>" для <.+>.
Это связано с тем, что QRegExp по умолчанию работает в режиме "жадного" поиска. Управлять этим свойством можно с помощью функции класса QRegExp - setMinimal().
Mikhail Спасибо за внимание к моей проблеме, но мне все же стоило сразу обратиться к гуглу и, конкретно, к офф. документации. Тема с масками QT слишком обширна для ответа в комментарии. Хотя было бы отлично почитать это на русском. Вот, собственно что я нашел http://doc.qt.io/qt-5/qregexp.html
Anonymous:
Mikhail Спасибо за внимание к моей проблеме, но мне все же стоило сразу обратиться к гуглу и, конкретно, к офф. документации. Тема с масками QT слишком обширна для ответа в комментарии. Хотя было бы отлично почитать это на русском. Вот, собственно что я нашел http://doc.qt.io/qt-5/qregexp.html
Если Вы пользуетесь Qt 5, то рекомендую обратить внимание на QRegularExpression: моя статья, официальная документация.
Anonymous
Как на счет актуального для Qt5 QRegularExpression?