C# 正则表达式匹配案例 - 拆分字符串并写入文件输出
Posted
技术标签:
【中文标题】C# 正则表达式匹配案例 - 拆分字符串并写入文件输出【英文标题】:C# Regex match case - split string and write to file output 【发布时间】:2017-06-11 23:05:23 【问题描述】:基本上我有一个这种格式的记录文本文件:
(1909, 'Ford', 'Model T'),
(1926, 'Chrysler', 'Imperial'),
(1948, 'Citroën', '2CV'),
我要输出到以下格式的文本文件
new Vehicle() Id = 1, Year = 1909, Make = "Ford", Model = "Model T" ,
new Vehicle() Id = 2, Year = 1926, Make = "Chrysler", Model = "Imperial" ,
new Vehicle() Id = 3, Year = 1948, Make = "Citroën", Model = "2CV" ,
我知道我需要将每一行分成相关的文本部分,例如尝试关注this SO 之类的问题。但是在如何获取年份、品牌和型号的相关匹配字符串部分时遇到了心理障碍。
到目前为止,我已经找到了这个,它可以在括号之间找到所有内容:
\(([^()]+)\)
但不确定如何将值分组并用逗号分隔:
非常感谢任何帮助。
【问题讨论】:
引用的字符串可以包含'('或')'吗?),
后面总是有换行符吗?
好吧,如果你想使用正则表达式,你可以试试^\((\d+)\s*,\s*'([^']*)'\s*,\s*'([^']*)'\),
【参考方案1】:
正则表达式将它们分组:
\((\d+),\s+[']([\w\së]+)['],\s+[']([\w\s]+)[']\)[,]*
请注意雪铁龙存在问题ën => 您必须输入所有不在 a-z、A-Z 范围内的特殊符号(如 ë ü ÿ 等)
要在代码中使用,您将获得第一组:
string cars = @"(1909, 'Ford', 'Model T'),"
string pattern = @"\((\d+),\s+[']([\w\së]+)['],\s+[']([\w\s]+)[']\)[,]*";
var lResult = Regex.Match(cars, pattern);
if(lResult.Success)
foreach( var iGroup in lResult.Groups)
Console.WriteLine(iGroup);
在 lResult.Groups 你得到了关于汽车的信息,你只是根据需要将它输出到文件中。
C# 6.0:
Console.WriteLine($"new Vehicle() Id = 1, Year = lResults.Groups[1], Make = \"lResults.Groups[2]\", Model = \"lResults.Groups[3]\",");
旧语法:
Console.WriteLine(@"new Vehicle() Id = 1, Year = "+ lMatch.Groups[1]+", Make = "+ lMatch.Groups[2] + ", Model = "+ lMatch.Groups[3] + " ,");
一旦你把它自动化到 for 循环中,你就可以很容易地添加 Id。
我的示例在 Groups[0] 中包含整个字符串,所以这就是为什么我的索引从 1 开始到 3。
正如@Toto所说,\w
已经包含\d
,那就不用写了。
【讨论】:
模型可能包含除字母/数字以外的其他字符 @Toto,谢谢,不知道 \d。如果还有其他字符,我们必须定义它们是什么字符 -> 从一些国家/通用字母表中获取。【参考方案2】:为什么不使用 string.Split(',')?会比正则表达式更快并且适合您(当然,首先删除每行的最后一个“,”。
【讨论】:
如果模型中有逗号会发生什么? 他的问题不清楚,我不知道他是否需要从文本文件读取到 modile 或反之亦然,但无论如何,在任何一种情况下,他都必须有一个用于字段的 deilmitar设置为唯一的 我确实可以使用字符串拆分,但认为正则表达式会更简洁? 不这么认为。 Split 更容易阅读,我认为它是为这类情况设计的。对于更复杂的情况,我会让正则表达式...保持简单 @Tatranskymedved 我会遵循 KISS 原则en.wikipedia.org/wiki/KISS_principle 如果系统模式始终相同,为什么要使用正则表达式?更难阅读,更难主要,不是为了这个目的。如果您的系统将来发生变化,那么考虑使用正则表达式,但现在不要使用正则表达式,因为将来它可能会改变......【参考方案3】:如果您愿意使用解析器框架(这可能有点矫枉过正),您可以使用例如sprache
。没有正确错误处理的示例:
Parser<string> stringContent =
from open in Parse.Char('\'').Once()
from content in Parse.CharExcept('\'').Many().Text()
from close in Parse.Char('\'').Once()
select content;
Parser<string> numberContent = Parse.Digit.AtLeastOnce().Text();
Parser<string> element = stringContent.XOr(numberContent);
Parser<List<string>> elements =
from e in element.DelimitedBy(Parse.Char(',').Token())
select e.ToList();
Parser<List<string>> parser =
from open in Parse.Char('(').Once()
from content in elements
from close in Parse.Char(')').Once()
select content;
var input = new List<string> "(1909, 'Ford', 'Model T')", "(1926, 'Chrysler', 'Imperial')", "(1948, 'Citroën', '2CV')" ;
foreach (var line in input)
var parsed = parser.Parse(line);
var year = Int32.Parse(parsed[0]);
var make = parsed[1];
var model = parsed[2];
Console.WriteLine(">> " + year + " " + make + " " + model);
【讨论】:
\w
已经包含\d
。您与 Citroën
中的 ë
不匹配(取决于区域设置)。模型可能包含除字母/数字以外的其他字符
@Toto 通过通用元组解析器修复【参考方案4】:
您可以根据命名的捕获组使用此 sn-p:
var cars = new List<string>()
"(1909, 'Ford', 'Model T')",
"(1926, 'Chrysler', 'Imperial')",
"(1948, 'Citroën', '2CV')",
;
var regex = @"(?<Year>\d+).*?'(?<Brand>.*?)'.*?'(?<Model>.*?)'";
foreach (var car in cars)
var match = Regex.Match(car, regex);
if (match.Success)
Console.WriteLine($"match.Groups["Brand"] make match.Groups["Model"] in match.Groups["Year"]");
将打印的内容:
福特在 1909 年制造 T 型车
克莱斯勒在 1926 年成为帝国汽车
1948 年雪铁龙制造 2CV
【讨论】:
以上是关于C# 正则表达式匹配案例 - 拆分字符串并写入文件输出的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式从字符串中精确匹配 11 位电话号码并从 C# 中的匹配中删除连字符(-)
Pandas使用split函数基于指定分隔符拆分数据列的内容为列表设置expand参数将拆分结果列表内容转化为多列数据并添加到原数据中replace函数基于正则表达式替换字符串数据列中的匹配内容