C# 替换为正则表达式
本文关键字:正则表达式 替换 | 更新日期: 2023-09-27 18:34:01
我是VB,C#的新手,并且正在努力解决正则表达式。我想我有以下代码格式将正则表达式匹配替换为文件中的空格。
编辑:根据评论,此代码块已更改。
var fileContents = System.IO.File.ReadAllText(@"C:'path'to'file.csv");
fileContents = fileContent.Replace(fileContent, @"regex", "(;
regex = new Regex(pattern);
regex.Replace(filecontents, "");
System.IO.File.WriteAllText(@"C:'path'to'file.csv", fileContents);
我的文件格式如下:
"1111111","22222222222","Text that may, have a comma, or two","2014-09-01",,,,,,
到目前为止,我已经正则表达式找到了 ,"
和 ",
之间包含逗号的任何字符串(第一个或最后一个单元格中永远不会有逗号,所以我不担心排除这两个。我正在 Expresso 中测试正则表达式
(?<=,")([^"]+,[^"]+)(?=",)
我只是不确定如何将该逗号隔离为需要替换的内容。最好的方法是什么?
解决:组合 [^"]+ 与后视/前瞻:
(?<=,"[^"]+)(,)(?=[^"]+",)
最终编辑:这是我最终的完整解决方案:
//read file contents
var fileContents = System.IO.File.ReadAllText(@"C:'path'to'file.csv");
//find all commas between double quotes
var regex = new Regex("(?<=,'")([^'"]+,[^'"]+(?='",)");
//replace all commas with ""
fileContents = regex.Replace(fileContents, m => m.ToString().Replace(",", ""));
//write result back to file
System.IO.File.WriteAllText(@"C:'path'to'file.csv", fileContents);
通过将 [^"]+ 与向前看?=
和向后看?<=
相结合来弄清楚,以便它找到以 ,"[anything that's not double quotes, one or more times]
开头的字符串,然后有一个逗号,然后以 [anything that's not double quotes, one or more times]",
结尾
(?<=,"[^"]+((,((?=[^"]+",(
尝试用这个解析出所有列:
Regex regex = new Regex("(?<='").*?(?='")");
然后你可以做:
foreach(Match match in regex.Matches(filecontents))
{
fileContents = fileContents.Replace(match.ToString(), match.ToString().Replace(",",string.Empty))
}
可能没有那么快,但应该可以工作。
我可能会使用 Regex.Replace 的重载,它需要一个委托来返回替换的文本。当您有一个简单的正则表达式来识别模式,但您需要为替换做一些不太简单(复杂逻辑(的事情时,这很有用。
我发现保持正则表达式简单会在您以后尝试维护它们时带来好处。
注意:这类似于@Florian的答案,但此替换仅限于在匹配的文本中替换。
string exp = "(?<=,'")([^'"]+,[^'"]+)(?='",)";
var regex = new Regex(exp);
string replacedtext = regex.Replace(filecontents, m => m.ToString().Replace(",",""))
你那里有一种不规则的语言。这是因为逗号可能意味着不同的东西,具体取决于它在文本流中的位置。奇怪的正则表达式旨在解析常规语言,其中逗号表示相同的内容,无论它在文本流中的哪个位置。不规则语言需要的是解析器。事实上,正则表达式主要用于在字符串输入解析器之前对字符串进行标记化。
虽然您尝试执行的操作可以使用正则表达式完成,但可能会非常慢。例如,您可以使用以下内容(即使逗号是字段中的第一个或最后一个字符,也可以使用(。但是,每次找到逗号时,它都必须前后扫描以检查它是否在两个引号字符之间。
(?<=,"[^"]*),(?=[^"]*",)
另请注意,它们可能是您尚未发现的此方法中的缺陷。我不知道您是否有这个问题,但通常在 CSV 文件中,您可以在也可能有逗号的字段中使用引号字符。在这些情况下,像MS Excel这样的应用程序通常会将报价加倍,以表明它不是字段的结尾。喜欢这个:
"1111111","22222222222","Text that may, have a comma, Quote"" or two","2014-09-01",,,,,,
在这种情况下,您将不走运地使用正则表达式。
值得庆幸的是,处理CSV文件的代码非常简单:
public static IList<string> ParseCSVLine(string csvLine)
{
List<string> result = new List<string>();
StringBuilder buffer = new StringBuilder();
bool inQuotes = false;
char lastChar = ''0';
foreach (char c in csvLine)
{
switch (c)
{
case '"':
if (inQuotes)
{
inQuotes = false;
}
else
{
if (lastChar == '"')
{
buffer.Append('"');
}
inQuotes = true;
}
break;
case ',':
if (inQuotes)
{
buffer.Append(',');
}
else
{
result.Add(buffer.ToString());
buffer.Clear();
}
break;
default:
buffer.Append(c);
break;
}
lastChar = c;
}
result.Add(buffer.ToString());
buffer.Clear();
return result;
}
附言。CSV文件经常会遇到另外几个问题,我给出的代码无法解决。首先是,如果字段中间有一个行尾字符,会发生什么情况?其次是你怎么知道CSV文件是什么字符编码?这两个问题中的前者很容易通过稍微修改我的代码来解决。然而,如果不与提供文件的人达成某种协议,第二种几乎是不可能的。