Я хочу удалить пустые строки во входной строке, используя regex_replace()
; однако регулярное выражение "^\n"
не работает в моем коде, хотя оно работает, когда я тестирую его на RegExr. Вот мой код:
std::string s = "filler text\n\nfiller text";
std::regex reg("^\n");
std::cout << s;
s = std::regex_replace(s, reg, "");
cout << '\n' << s;
Выходы:
filler text
filler text
filler text
filler text
Должен ли я просто прибегнуть к замене любых двух символов новой строки только одним? Тогда мне придется зацикливаться, пока совпадений не будет найдено. Почему этот метод не работает, хотя, казалось бы, в нем нет ничего плохого?
Зачем вам нужно регулярное выражение? Просто замените \n\n
на \n
.
Обратите внимание: даже если бы это сработало, вам все равно понадобится цикл, потому что regex_replace()
не заменяет перекрывающиеся совпадения.
@Chris Поскольку это пустая строка, в ней нет ничего, кроме новой строки.
@Barmar Что вы имеете в виду, говоря не заменять перекрывающиеся совпадения?
Помогает ли определение вашего регулярного выражения с помощью необработанной строки? stackoverflow.com/q/56710024
C++17: используйте std::regex_constants::multiline
@Barmar, удалив все непересекающиеся пустые строки, не может создать новые пустые строки, здесь нет перекрытий...
Почему мой вопрос был закрыт из-за дубликата? Тот факт, что ^
и $
совпадают с началом и концом строки, всегда не влияет на мой вопрос, поскольку я уже учел это.
О, это только в MSVC?
Предположим, есть 4 последовательных символа новой строки (3 пустые строки). ^\n
заменит вторую новую строку в каждой паре, поэтому результатом будут 2 последовательные новые строки, поэтому остается пустая строка.
@STerliakov Он не создает новых строк, но не может удалить все пустые строки.
@Barmar Почему он заменяет только вторую часть каждой пары? Я проверил ваш сценарий на RexExr, но этого не произошло.
Методом кувалды было бы поместить строку в stringstream
, прочитать ее обратно с помощью getline
и отбросить пустые строки.
@YoussefGamil Я был неправ, поскольку привязка представляет собой утверждение нулевой ширины, поэтому не считается частью совпадения.
Открыто вновь - номинированный обман не был (даже близок) к настоящему обману.
Хм, @Barmar, тогда это, вероятно, что-то специфическое для регулярного выражения С++, извини. Python r'(?m)^\n'
удалит все пустые строки, а не только некоторые из них... Вероятно, это эквивалентно режиму std::regex_constants::multiline
, предложенному выше?
@YoussefGamil Пожалуйста, не используйте для этого регулярное выражение. Пока у нас не будет регулярного выражения constexpr
и возможности оптимизировать такие простые задачи, как эта, это будет очень медленно по сравнению с простым поиском/заменой. Сравнение
Как и почти каждый вопрос о регулярных выражениях, который я видел за последние десять лет, это совершенно тривиально, если вы не используете регулярные выражения, и, в лучшем случае, сложно и непонятно, если вы их используете. Я всегда считал, что добавление библиотеки регулярных выражений было ошибкой.
@PeteBecker Хе. У вас есть проблема. Вы решаете использовать регулярное выражение. Теперь у вас две проблемы...
Я делаю это с <ranges>
: auto refined = source | std::views::split('\n') | std::views::filter(std::not_fn(std::ranges::empty)) | std::views::join('\n') | std::ranges::to<std::string>();
Вместо того, чтобы иметь дело с «концом строки», я бы просто заменил несколько последовательных новых строк одной новой строкой:
#include <iostream>
#include <string>
#include <regex>
int main(int argc, char **argv) {
std::string s = "filler text\n\nfiller text";
std::regex reg("\n+");
std::cout << "Before:\n";
std::cout << s << "\nAfter:\n";
s = std::regex_replace(s, reg, "\n");
std::cout << '\n' << s << '\n';
}
Результат выглядит следующим образом:
Before:
filler text
filler text
After:
filler text
filler text
Как вы ожидаете найти новую строку в начале строки?