好吧,这个答案符合赏金中明确的要求:
我还需要删除任何尾随换行符,我的 Regex-fu 是
失败。我的赏金给任何能给我一个通过的正则表达式的人
这个测试: StripWhitespace("test\r\n \r\nthis\r\n\r\n") ==
“测试\r\n这个”
答案如下:
(?<=\r?\n)(\s*$\r?\n)+|(?<=\r?\n)(\r?\n)+|(\r?\n)+\z
或者在@Chris Schmich提供的C#代码中:
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)
- 文件末尾的空格