通常,我喜欢正则表达式的挑战,甚至更好 - 解决它们.
但似乎我有一个我无法弄清楚的案例.
我有一串值,用CSV格式的分号分隔,看起来像这样:
123-234;FOO-456;45-67;FOO-FOO;890;FOO-123;11-22;123;123;44-55;098-567;890;123-FOO;
在这一行中,我想匹配所有整数和整数范围,以便稍后提取它们.有可能只有单个值(没有分号).
经过大量的搜索,我设法写了这个表达式:
(?:^|;)(?<range>\d+-\d+)(?:$|;)|(?:^|;)(?<integer>\d+)(?:$|;)
我正在使用的测试字符串:
123123-234;FOO-456;45-67;FOO-FOO;890;FOO-123;11-22;123;123;44-55;098-567;890;123-FOO;123-456123-FOOFOO-123FOO-FOO第1行和第3行正确匹配,第4,5行不正确.
在第2行中,只有一个值正确匹配.
下面是regex101.com一个链接,说明它:https://regex101.com/r/zA7uI9/5
我还需要分别选择整数和范围(在不同的组中).
注意:我发现了一个可以帮助我并尝试答案的问题(通过调整),但它没有用.
用于匹配数字和数字范围的正则表达式
你知道我错过了什么吗?
将"使用"此正则表达式的语言是C#,但我不知道它是否对我的问题有用.
由barlop添加
以下是当前正则表达式给出的匹配,如regex101.com链接所示
并为他的这个测试字符串 123-234;FOO-456;45-67;FOO-FOO;890;FOO-123;11-22;123;123;44-55;098-567;89
123-234
45-67
890
11-22
123
098-567
Run Code Online (Sandbox Code Playgroud)
所以他的正则表达式似乎错过了123中的一个,44-45和最后的89.
使用内置的CSV解析器并分别检查每个字段:
using Microsoft.VisualBasic.FileIO;
....
var str = "123-234;FOO-456;45-67;FOO-FOO;890;FOO-123;11-22;123;123;44-55;098-567;890;123-FOO;";
var csv_parser = new TextFieldParser(new StringReader(str));
csv_parser.HasFieldsEnclosedInQuotes = false; // Fields are not enclosed with quotes
csv_parser.SetDelimiters(";"); // Setting delimiter
string[] fields;
var range_fields = new List<string>();
var integer_fields = new List<string>();
while (!csv_parser.EndOfData)
{
fields = csv_parser.ReadFields();
foreach (var field in fields)
{
if (!string.IsNullOrWhiteSpace(field) && field.All(x => Char.IsDigit(x)))
{
integer_fields.Add(field);
Console.WriteLine(string.Format("Intger field: {0}", field));
}
else if (!string.IsNullOrWhiteSpace(field) && Regex.IsMatch(field, @"\d+-\d+"))
{
range_fields.Add(field);
Console.WriteLine(string.Format("Range field: {0}", field));
}
}
}
csv_parser.Close();
Run Code Online (Sandbox Code Playgroud)
结果是:
Range field: 123-234
Range field: 45-67
Intger field: 890
Range field: 11-22
Intger field: 123
Intger field: 123
Range field: 44-55
Range field: 098-567
Intger field: 890
Run Code Online (Sandbox Code Playgroud)
原因您正则表达式失败是你实际消耗的符与非捕获组(即(?:^|;)和(?:$|;)仍然匹配的文本,该文本被附加到匹配值,和正则表达式指数是先进的后的位置;,开始/结束的字符串).
您需要使用的是外观.它们不消耗文本,只检查是否可以在当前位置之前或之后找到与环绕模式匹配的文本.因此,您有机会获得重叠匹配,并且这是场景非常方便的场景之一.
(?<=^|;)((?<range>\d+-\d+)|(?<integer>\d+))(?=$|;)
Run Code Online (Sandbox Code Playgroud)
支持RegexStorm的.NET正则表达式语法的.NET正则表达式的正则表达式演示
一个很好的图表:
注意RegexOptions.ExplicitCapture标志的使用:这样,我们避免使用编号(即未命名的)捕获组捕获子匹配,只获取命名的捕获(正是我们需要的).
var s = "123-234;FOO-456;45-67;FOO-FOO;890;FOO-123;11-22;123;123;44-55;098-567;890;123-FOO;";
var rx = new Regex(@"(?<=^|;)((?<range>\d+-\d+)|(?<integer>\d+))(?=$|;)", RegexOptions.ExplicitCapture);
var result = rx.Matches(s)
.Cast<Match>()
.Select(x => x.Groups["range"].Success ?
x.Groups["range"].Value : x.Groups["integer"].Value
).ToList();
foreach (var x in result)
Console.WriteLine(x);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |