Есть ли простой способ заменить только первое вхождение некоторой подстроки другой подстрокой в QString? Он может быть в любом положении.
QString заменяет только первое вхождение
Ответы (4)
Вы можете попробовать это:
QString str("this is a string"); // The initial string.
QString subStr("is"); // String to replace.
QString newStr("at"); // Replacement string.
str.replace(str.indexOf(subStr), subStr.size(), newStr);
Результирующая строка будет:
что на веревке
QRegExp
есть matchedLength()
, а у QRegularExpressionMatch
есть capturedLength()
- в чем проблема?
- person Toby Speight; 05.07.2016
Не существует удобного метода для операции, которую вы хотите иметь. Однако вы можете использовать следующие два метода для создания пользовательской операции:
Возвращает позицию индекса первого вхождения строки str в этой строке, выполняя поиск вперед от позиции индекса. Возвращает -1, если строка не найдена.
Если cs равно Qt::CaseSensitive (по умолчанию), поиск чувствителен к регистру; в противном случае поиск нечувствителен к регистру.
а также
QString и QString::replace(int position, int n, const QString & после)
Заменяет n символов, начиная с позиции индекса, строкой после и возвращает ссылку на эту строку.
Примечание. Если указанный индекс позиции находится в пределах строки, но position + n выходит за пределы диапазона строк, то n будет скорректирован так, чтобы он останавливался в конце строки.
Теперь, применив все это на практике, вы могли бы написать что-то вроде следующего:
main.cpp
#include <QString>
#include <QDebug>
int main()
{
QString initialString = QLatin1String("foo bar baz");
QString fooString = QLatin1String("foo");
initialString.replace(initialString.indexOf(fooString),
fooString.size(), QLatin1String("stuff"));
qDebug() << initialString;
return 0;
}
main.pro
TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp
Построить и запустить
qmake && make && ./main
Выход
"stuff bar baz"
Это почти так, как это делает QString::replace(QRegularExpression, .... Поскольку буквальные обратные косые черты могут быть частью шаблона замены, они должны быть захвачены по-разному. Обратите внимание, что фактическая замена происходит справа налево. сохранить правильность смещения влево.Можно выразить это более компактно, но в таком виде его легче отлаживать.
QRegularExpression regex = QRegularExpression(regex_pattern);
if (regex.isValid() and
(regex_pattern.length() > 0)) {
QRegularExpressionMatchIterator regex_iterator =
regex.globalMatch(target_text, Apply_Target_Offset,
QRegularExpression::PartialPreferCompleteMatch);
if (regex_iterator.hasNext()) {
// At least one found
QRegularExpressionMatch match = regex_iterator.next();
if (match.hasMatch() and (not match.hasPartialMatch())) {
// This is the first match, and it's complete
int match_begin = match.capturedStart();
int match_end = match.capturedEnd();
int match_length = match.capturedLength();
QStringList captured;
const int capture_groups_count = regex.captureCount() + 1;
for (int capture_group_idx = 0; capture_group_idx < capture_groups_count; ++capture_group_idx) {
captured.append(match.captured(capture_group_idx));
}
QString replace_pattern = Apply_Replace_Pattern->toPlainText();
QString replace_text = replace_pattern;
QList<QRegularExpressionMatch> replace_pattern_match_list;
QRegularExpression replace_pattern_regex = QRegularExpression("(?:\\\\\\\\)+|(?:\\\\(\\d+))");
if (replace_pattern_regex.isValid()) {
QRegularExpressionMatchIterator replace_pattern_regex_iterator =
replace_pattern_regex.globalMatch(replace_pattern);
while (replace_pattern_regex_iterator.hasNext()) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_regex_iterator.next();
bool no_error;
replace_pattern_match.captured().right(1).toInt(&no_error);
// Only accept backreferences w/ numbers
if (no_error) replace_pattern_match_list.append(replace_pattern_match);
}
while (replace_pattern_match_list.count() > 0) {
QRegularExpressionMatch replace_pattern_match = replace_pattern_match_list.takeLast();
int cap_idx = replace_pattern_match.captured(1).toInt();
if (cap_idx < captured.count()) {
replace_text.replace(replace_pattern_match.capturedStart(),
(replace_pattern_match.capturedEnd() -
replace_pattern_match.capturedStart()),
captured[cap_idx]);
}
}
// Render '\' characters properly
replace_text.replace("\\\\", "\\");
}
target_text.replace(match_begin, (match_end - match_begin), replace_text);
}
}
}