我正在寻找RegEx模式的一些指导。
我有一个管道分隔文件,我和我想要删除第四个单元格为空的所有行。每行可以有任意数量的单元格。
到目前为止我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace EpicRemoveBlankPriceRecords
{
class Program
{
static void Main(string[] args)
{
string line;
// Read the file and display it line by line.
System.IO.StreamReader inFile = new System.IO.StreamReader("c:\\test\\test.txt");
System.IO.StreamWriter outFile = new System.IO.StreamWriter("c:\\test\\test_out.txt");
while ((line = inFile.ReadLine()) != null)
{
Match myMatch = Regex.Match(line, @".*\|.*\|.*\|\|.*");
if (!myMatch.Success)
{
outFile.WriteLine(line);
}
}
inFile.Close();
outFile.Close();
//// Suspend the screen.
//Console.ReadLine();
}
}
}
这不起作用。我认为这是因为RegEx是“贪婪的” - 如果有任何空白单元格,这匹配,因为我没有明确说“除了管道字符之外的所有东西”。一个快速的谷歌,我看到我可以使用模式中的[^ \ |]来做到这一点。
所以,如果我将模式更改为:
".*[^\|]\|.*[^\|]\|.*[^\|]\|\|.*"
为什么这不起作用?
猜猜我有点困惑,任何指针都会非常感激。
谢谢!
答案 0 :(得分:2)
你真的需要正则表达式吗?
var lines = File.ReadLines(filename)
.Where(line => !String.IsNullOrWhiteSpace(line.Split('|')[3]));
File.WriteAllLines(outfile, lines);
答案 1 :(得分:1)
.*[^\|]
表示零个或多个通配符(.*
)和一个不是|
([^\|]
)的字符。
此外,您需要在|
内转义[]
。
并且Regex.Match
实际上并不匹配,它会搜索,因此您需要在正则表达式的开头^
(表示字符串的开头)。
因此也不需要尾随.*
。
您需要零个或多个不是|
的字符,如下所示:
"^[^|]*\|[^|]*\|[^|]*\|\|"
为什么".*\|.*\|.*\|\|.*"
无效?
除上述原因外......
*
贪婪并没有太大改变(你可以通过.*?
来使它变得非贪婪/懒惰)。问题是.
也匹配|
并且它回溯,因此.*
将包含与字符串匹配所需的|
个{{1}}(是的) ,它会尝试包含更多,因为它是贪婪的,但这不会改变它是否找到了什么,只有它找到的东西。
你可以使用延迟匹配和possessive quantifiers一起破解某些东西,但最终会变得更复杂,更重要的是,我认为,C#不支持这些。
答案 2 :(得分:1)
这似乎适用于regexpal:
^[^|]*\|[^|]*\|[^|]*\|\|.*
^
单独表示行首[^|]
除|
[^|]*
匹配零个或多个非|
字符+
可能对您的使用有误,但这意味着至少有一个,但发现的更多.*
意味着任何事情,以及尽可能多的事情。测试数据: