Создание регулярного выражения для удаления последовательных пробелов, кроме новых строк - PullRequest
0 голосов
/ 03 марта 2019

Я хотел бы использовать регулярное выражение для выполнения следующих действий:

  • Все пробельные символы, кроме символов новой строки, должны быть преобразованы в пробел (т. Е. \f, \r, \t, \v будет преобразовано в пробел)
  • Строка не может иметь два или более последовательных пробела, кроме символов новой строки.
    • Символы новой строки ограничены максимум двумя последовательными вхождениями (т. Е. \n - это нормально, \n\n - тоже хорошо, но \n\n\n недопустимо и должно быть заменено на \n\n).
  • Если пробелу предшествует или следует новая строка, пробел должен быть удален.

Некоторые примеры:

space-space => space
space-space-space => space
space-tab => space
space-tab-space => space
newline-newline => newline-newline
space-newline => newline
space-newline-newline => newline-newline
newline-space => newline
newline-space-newline => newline-newline

Единственное регулярное выражениеЯ мог бы придумать, пока это было так, и он удаляет все последовательные пробелы:

Regex.Replace(input, @"(\s)\s+", "$1");

Ответы [ 2 ]

0 голосов
/ 03 марта 2019

Для сопоставления с любым пробелом, кроме новой строки, вы можете использовать [^\S\n] отрицательный класс символов.Или [\s-[\n]], но я предпочитаю первый, так как он переносим на другие движки регулярных выражений.

Теперь вы можете использовать регулярное выражение, которое будет сопоставлять необязательные символы новой строки слева и справа от 1+ пробелов.кроме новой строки.Затем вы можете проверить, совпадали ли какие-либо символы новой строки, и, если да, опустить пропущенный пробел, в противном случае заменить совпадение пробелом.Затем вам нужно будет заменить любые фрагменты из 3 или более символов новой строки двумя символами новой строки.

var result = Regex.Replace(input, @"(\n?)[^\S\n]+(\n?)", m =>
    !string.IsNullOrEmpty(m.Groups[1].Value) || !string.IsNullOrEmpty(m.Groups[2].Value) // If any \n matched
        ? $"{m.Groups[1].Value}{m.Groups[2].Value}" // Concat Group 1 and 2 values
        : " ");  // Else, replace the 1+ whitespaces matched with a space
var final_result = Regex.Replace(result, @"\n{3,}", "\n\n"); // Replace 3+ \ns with two \ns

Подробности

  • (\n?) - Захват группы 1: необязательный символ новой строки
  • [^\S\n]+ - 1+ пробелов, кроме новой строки
  • (\n?) - Группа захвата 2: необязательный символ новой строки
  • \n{3,} - 3 или болеепереводы строки.
0 голосов
/ 03 марта 2019

Простое многошаговое решение выглядит следующим образом:

Все пробельные символы, за исключением символов новой строки, должны быть преобразованы в пробел (т.е. будут преобразованы \ f, \ r, \ t, \ vна пробел)

output = Regex.Replace(input, "[\\f\\r\\t\\v ]+", " ");

Пробел входит в указанную выше группу.

Если пробел предшествует или следует за новой строкой, пробел должен быть удален.

output = Regex.Replace(output, " \n", "\n");
output = Regex.Replace(output, "\n ", "\n"); 

Вместо этих двух можно вместо этого использовать String.Replace в стиле:

output = output.Replace(" \n", "\n");
output = output.Replace("\n ", "\n");

или даже:

output = output.Replace(" \n", "\n").Replace("\n ", "\n");

Строка не может иметь два или более последовательных пробела, кроме новых строк.Символы новой строки ограничены максимум двумя последовательными вхождениями (т. Е. \ N в порядке, \ n \ n тоже в порядке, но \ n \ n \ n недопустимо и должно быть заменено на \ n \ n).

output = Regex.Replace(output, "\n\n\n+", "\n\n");

В сторону.Если система использует \r\n для последовательностей новой строки, то подавление символов \r может привести к нежелательным результатам.

...