Хорошо, этот ответ соответствует уточненным требованиям, указанным в награде:
Мне также нужно удалить любые завершающие символы новой строки, и мой Regex-fu
терпит неудачу. Моя награда достается любому, кто может дать мне регулярное выражение, которое проходит
этот тест: StripWhitespace ("test \ r \ n \ r \ nthis \ r \ n \ r \ n") ==
"тест \ г \ nЭто"
Так вот ответ:
(?<=\r?\n)(\s*$\r?\n)+|(?<=\r?\n)(\r?\n)+|(\r?\n)+\z
Или в коде C #, предоставленном @Chris Schmich:
string fix = Regex.Replace("test\r\n \r\nthis\r\n\r\n", @"(?<=\r?\n)(\s*$\r?\n)+|(?<=\r?\n)(\r?\n)+|(\r?\n)+\z", string.Empty, RegexOptions.Multiline);
Теперь давайте попробуем это понять. Здесь есть три дополнительных шаблона, которые я готов заменить на string.empty
.
(?<=\r?\n)(\s*$\r?\n)+
- соответствует одной неограниченной строке, содержащей только пробел и которой предшествует разрыв строки (но не соответствует первым предыдущим разрывам строки).
(?<=\r?\n)(\r?\n)+
- соответствует одной неограниченной пустой строке без содержимого, которому предшествует разрыв строки (но не соответствует первым предыдущим разрывам строки).
(\r?\n)+\z
- соответствует одному неограниченному разрыву строки в конце тестируемой строки (завершающие разрывы строк, как вы их называли)
Это отлично удовлетворяет вашему тесту! Но также удовлетворяет как \r\n
, так и \n
стилям разрыва строки! Проверьте это! Я полагаю, что это будет самый правильный ответ, хотя более простое выражение пройдет указанный вами тест на вознаграждение, это регулярное выражение пройдет более сложные условия.
РЕДАКТИРОВАТЬ: @Will указал потенциальный недостаток в последнем сопоставлении с шаблоном вышеупомянутого регулярного выражения в том, что он не будет соответствовать нескольким разрывам строк, содержащих пробел в конце тестовой строки. Итак, давайте изменим этот последний шаблон на этот:
\b\s+\z
\ b - это граница слова (начало или конец слова), \ s + - один или несколько символов пробела, \ z - конец тестовой строки (конец «файла») , Так что теперь он будет соответствовать любому ассортименту пробелов в конце файла, включая вкладки и пробелы в дополнение к возврату каретки и разрывам строк. Я протестировал оба тестовых примера @Will.
Итак, все вместе теперь должно быть:
(?<=\r?\n)(\s*$\r?\n)+|(?<=\r?\n)(\r?\n)+|\b\s+\z
РЕДАКТИРОВАТЬ # 2: Хорошо, есть еще один возможный случай @Wil обнаружил, что последнее регулярное выражение не распространяется. В этом случае входные данные имеют разрывы строк в начале файла перед любым содержимым. Итак, давайте добавим еще один шаблон, соответствующий началу файла.
\A\s+
- \A
соответствует началу файла, \s+
соответствует одному или нескольким символам пробела.
Так что теперь у нас есть:
\A\s+|(?<=\r?\n)(\s*$\r?\n)+|(?<=\r?\n)(\r?\n)+|\b\s+\z
Итак, теперь у нас есть четыре шаблона для сопоставления:
- пробел в начале файла,
- избыточные разрывы строк, содержащие пробелы, (например:
\r\n \r\n\t\r\n
)
- избыточные разрывы строк без содержимого (например:
\r\n\r\n
)
- пробел в конце файла