在C#中删除空行的最佳方法是什么,即只包含字符串空格的行?如果这是最好的解决方案,我很高兴使用正则表达式。
编辑:我应该添加我使用的是.NET 2.0。
Bounty更新:奖励之后我会回滚,但我想澄清一些事情。
首先,任何Perl 5 compat正则表达式都可以。这不仅限于.NET开发人员。标题和标签已经过编辑以反映这一点。
其次,虽然我在赏金细节中给出了一个快速示例,但它不是您必须满足的唯一测试。您的解决方案必须删除除<空> 以及最后一个换行符之外的所有行。如果有一个字符串,在运行正则表达式后,以“/ r / n”或任何空格字符结尾,则会失败。
答案 0 :(得分:20)
如果要删除包含任何空格(制表符,空格)的行,请尝试:
string fix = Regex.Replace(original, @"^\s*$\n", string.Empty, RegexOptions.Multiline);
编辑(对于@Will):修剪尾随换行符的最简单方法是在结果字符串上使用TrimEnd
,例如:
string fix =
Regex.Replace(original, @"^\s*$\n", string.Empty, RegexOptions.Multiline)
.TrimEnd();
答案 1 :(得分:16)
string outputString;
using (StringReader reader = new StringReader(originalString)
using (StringWriter writer = new StringWriter())
{
string line;
while((line = reader.ReadLine()) != null)
{
if (line.Trim().Length > 0)
writer.WriteLine(line);
}
outputString = writer.ToString();
}
答案 2 :(得分:13)
脱离我的头顶......
string fixed = Regex.Replace(input, "\s*(\n)","$1");
转过来:
fdasdf asdf [tabs] [spaces] asdf
进入这个:
fdasdf asdf asdf
答案 3 :(得分:8)
使用LINQ:
var result = string.Join("\r\n",
multilineString.Split(new string[] { "\r\n" }, ...None)
.Where(s => !string.IsNullOrWhitespace(s)));
如果您正在处理大型输入和/或不一致的行结尾,您应该使用StringReader并使用foreach循环执行上述旧学校。
答案 4 :(得分:3)
var o = JsonConvert.DeserializeObject(prettyJson);
new minifiedJson = JsonConvert.SerializeObject(o, Formatting.None);
答案 5 :(得分:3)
好的,这个答案符合赏金中规定的明确要求:
我还需要删除任何尾随的换行符,而我的正则表达式是 失败。我的赏金给任何可以给我一个通过的正则表达式的人 这个测试:StripWhitespace(“测试\ r \ n \ r \ n这个\ 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
)答案 6 :(得分:2)
为了回应Will的赏金,它需要一个需要"test\r\n \r\nthis\r\n\r\n"
和输出"test\r\nthis"
的解决方案,我想出了一个利用atomic grouping的解决方案(又名{{3在MSDN上)。我建议阅读这些文章,以便更好地了解正在发生的事情。最终,原子组帮助匹配原本留下的后续换行符。
使用RegexOptions.Multiline
这种模式:
^\s+(?!\B)|\s*(?>[\r\n]+)$
以下是一些测试用例的示例,其中包括一些我从Will对其他帖子的评论以及我自己的评论中收集到的一些测试用例。
string[] inputs =
{
"one\r\n \r\ntwo\r\n\t\r\n \r\n",
"test\r\n \r\nthis\r\n\r\n",
"\r\n\r\ntest!",
"\r\ntest\r\n ! test",
"\r\ntest \r\n ! "
};
string[] outputs =
{
"one\r\ntwo",
"test\r\nthis",
"test!",
"test\r\n ! test",
"test \r\n ! "
};
string pattern = @"^\s+(?!\B)|\s*(?>[\r\n]+)$";
for (int i = 0; i < inputs.Length; i++)
{
string result = Regex.Replace(inputs[i], pattern, "",
RegexOptions.Multiline);
Console.WriteLine(result == outputs[i]);
}
编辑:为了解决模式无法使用空格和换行符混合清理文本的问题,我将\s*
添加到正则表达式的最后一个替换部分。我之前的模式是多余的,我意识到\s*
会处理这两种情况。
答案 7 :(得分:1)
string corrected =
System.Text.RegularExpressions.Regex.Replace(input, @"\n+", "\n");
答案 8 :(得分:1)
这是另一种选择:使用StringReader
类。优点:一次遍历字符串,不创建中间数组。
public static string RemoveEmptyLines(this string text) {
var builder = new StringBuilder();
using (var reader = new StringReader(text)) {
while (reader.Peek() != -1) {
string line = reader.ReadLine();
if (!string.IsNullOrWhiteSpace(line))
builder.AppendLine(line);
}
}
return builder.ToString();
}
注意:IsNullOrWhiteSpace
方法为new in .NET 4.0。如果你没有这个,那么自己写一点是微不足道的:
public static bool IsNullOrWhiteSpace(string text) {
return string.IsNullOrEmpty(text) || text.Trim().Length < 1;
}
答案 9 :(得分:1)
我会选择:
public static string RemoveEmptyLines(string value) {
using (StringReader reader = new StringReader(yourstring)) {
StringBuilder builder = new StringBuilder();
string line;
while ((line = reader.ReadLine()) != null) {
if (line.Trim().Length > 0)
builder.AppendLine(line);
}
return builder.ToString();
}
}
答案 10 :(得分:1)
为了回应Will的赏金,这里有一个Perl sub,可以对测试用例给出正确的答案:
sub StripWhitespace {
my $str = shift;
print "'",$str,"'\n";
$str =~ s/(?:\R+\s+(\R)+)|(?:()\R+)$/$1/g;
print "'",$str,"'\n";
return $str;
}
StripWhitespace("test\r\n \r\nthis\r\n\r\n");
<强>输出:强>
'test
this
'
'test
this'
为了不使用\R
,请将其替换为[\r\n]
并反转替代方案。这个产生相同的结果:
$str =~ s/(?:(\S)[\r\n]+)|(?:[\r\n]+\s+([\r\n])+)/$1/g;
不需要特殊配置和多线支持。不过,如果强制要求,您可以添加s
标记。
$str =~ s/(?:(\S)[\r\n]+)|(?:[\r\n]+\s+([\r\n])+)/$1/sg;
答案 11 :(得分:1)
如果只有White空格,为什么不使用C#字符串方法
string yourstring = "A O P V 1.5";
yourstring.Replace(" ", string.empty);
结果将是“AOPV1.5”
答案 12 :(得分:0)
我不确定是否有效,但=)
List<string> strList = myString.Split(new string[] { "\n" }, StringSplitOptions.None).ToList<string>();
myString = string.Join("\n", strList.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList());
答案 13 :(得分:0)
字符串扩展
public static string UnPrettyJson(this string s)
{
try
{
// var jsonObj = Json.Decode(s);
// var sObject = Json.Encode(value); dont work well with array of strings c:['a','b','c']
object jsonObj = JsonConvert.DeserializeObject(s);
return JsonConvert.SerializeObject(jsonObj, Formatting.None);
}
catch (Exception e)
{
throw new Exception(
s + " Is Not a valid JSON ! (please validate it in http://www.jsoneditoronline.org )", e);
}
}
答案 14 :(得分:0)
的Eh。好吧,经过这一切,我找不到一个可以击中我能想到的所有角落情况。以下是我最新的正则表达式删除
(?&LT; =(\ r \ n)的| ^)\ S * \ r \ n | \ r \ n \ S * $
基本上说:
前半部分捕获字符串开头的所有空格,直到第一个非空白行,或非空白行之间的所有空格。下半部分阻塞了字符串中剩余的空格,包括最后一个非空白行的换行符。
感谢所有试图提供帮助的人;你的答案帮助我思考了匹配时我需要考虑的一切。
*(此正则表达式认为换行符为\r\n
,因此必须根据字符串的来源进行调整。不需要设置选项以运行匹配。)
答案 15 :(得分:0)
如果针对每一条线工作,这是一件简单的事情......
(^\s+|\s+|^)$
答案 16 :(得分:0)
char[] delimiters = new char[] { '\r', '\n' };
string[] lines = value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
string result = string.Join(Environment.NewLine, lines)
答案 17 :(得分:-1)
试试这个。
string s = "Test1" + Environment.NewLine + Environment.NewLine + "Test 2";
Console.WriteLine(s);
string result = s.Replace(Environment.NewLine, String.Empty);
Console.WriteLine(result);
答案 18 :(得分:-2)
s = Regex.Replace(s, @"^[^\n\S]*\n", "");
[^\n\S]
匹配任何不是换行符或非空白字符的字符 - 因此,除了\n
之外的任何空白字符。但很可能你唯一需要担心的是空格,制表符和回车符,所以这也应该有效:
s = Regex.Replace(s, @"^[ \t\r]*\n", "");
如果你想让它抓住最后一行,没有最后的换行符:
s = Regex.Replace(s, @"^[ \t\r]*\n?", "");