字符串有几种变体:
"txt files `(*.txt)|*.txt|All files (*.*)|*.*`"
"Image Files`|*.jpg;*.jpeg;*.png;`"
"Excel Files `(*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv`"
子字符串可以以任何字符(space, ',', '.', '|', ';') -
结尾,这无关紧要。
尝试了以下选项:;[^*].{3,4}(.?);", "[^*]+.(.?);
";。
我需要一个正则表达式来获得string[] = {.jpg, .jpeg, ...}
,最好没有重复元素。
您真的需要正则表达式吗?
首先,如果按|
分割,结果中的每个奇数条目都是一个扩展列表。然后,您可以通过;
再次拆分以获得扩展,然后可以将扩展展平为单个序列,并修剪起始*
的每个元素。最后,获取其不同的集合,并将其放入一个数组中。
这一切都可以用Split
和Linq:来实现
var extensions = filter.Split('|', StringSplitOptions.RemoveEmptyEntries)
.Where((x, i) => i % 2 != 0)
.SelectMany(x => x.Split(';', StringSplitOptions.RemoveEmptyEntries))
.Select(x => x.TrimStart('*'))
.Distinct()
.ToArray();
从拆分中删除空条目可以确保如果以分隔符结束,它将被忽略。
在.NET Fiddle上查看它的实际操作。
简单拆分
我想我也会用Split
来做,应该可以这样做:
str.Split('*',';','|')
.Where(s => s.StartsWith(".") && s[1..].All(Char.IsLetterOrDigit))
.Distinct();
注:这并没有对延期的长度做出任何坚持。如果你愿意,你可以在Where中添加一些内容,例如:
&& s.Length is >3 and <6
一个3或4长度的延长线与点的长度在4和5之间;大于3且小于6〃;来自。请注意,它使用了模式匹配,这是最近添加的c#。如果你的c#比较老,你需要一些老式的长度检查。。
Regex
但作为Regex的学习机会,使用捕获组从字符串中提取文件扩展名更容易
var r = new Regex(@"*(?<x>.w{3,4})b");
var arr = r.Matches()
.Cast<Match>()
.Select(m => m.Groups["x"].Value)
.Distinct();
Regex本身查找一个文本*
,然后开始用(?<x>
将字符捕获到一个名为x的组中。捕获的字符是:一个文字点,后面跟着3到4个单词字符(a-z,0-9)。我选择了3和4,因为您的代码选择了这一点,但请注意,扩展可能会更少或更多,所以您可以对此进行调整。Regex的最后一位要求在3或4个字符后有一个单词边界b
,因为我们不希望扩展名的部分匹配超过4个字符。单词边界意味着扩展在的3或4个字符之后完成(下一个字符是非单词字符)
要使用LINQ从中提取数据,我们必须执行类似Cast
的操作,将生成的集合条目转换为Match;它们已经是Matches了,但MatchCollection没有实现IEnumerable<T>
,因为它很旧,所以它不兼容LINQ,除非我们做一些像Cast这样的事情来实现它。
Select
从捕获组中检索字符串值,该组是.xxx
扩展,Distinct
删除重复的
您的Regex
至于为什么你的尝试没有奏效:
[^*]
.{3,4}
(.?)
;
这与匹配
- char,它是除星号之外的任何字符
- 然后是3或4个任何炭
- 然后是捕获到未命名组中的任何字符中的零个或一个
- 后跟分号">
在某些情况下,它可能会被调整以工作,但它似乎没有指定您正在寻找的字符模式
[^*]+
.
(.?)
;
这与匹配
- 一个或多个字符,该字符是除星号之外的任何字符
- 然后是任何炭
- 然后是捕获到未命名组中的任何字符中的零个或一个
- 后跟分号">
我怀疑你认为^
是一个允许匹配字面*
的转义符-转义符是,
当CCD_ 23用作CCD_;除";所以在我怀疑你试图匹配一个字面上的星号的地方,你实际上匹配了完全相反的
事实上,大多数字符在放置在字符类中时都会失去其特殊意义,因此CCD_;匹配文字星号";就像*
是
您的示例字符串似乎由括号之间的可选前导部分组成,后跟管道|
,然后是扩展名。
如果要匹配数据的格式,可以使用具有相同名称的捕获组和group.Captures属性。
b[fF]ilesb[^*()]*(?:([^()]*))?|*(?<ext>.[w*]+)(?:[,;]*(?<ext>.[w*]+))*
在某些部分,模式匹配:
b[fF]ilesb
匹配文件或文件[^*()]*
可选匹配除*
(
)
之外的任何字符(?:([^()]*))?
(可选)匹配括号之间的部分|*
匹配|*
(?<ext>.[w*]+)
命名组ext,匹配.
和单词char或*
的1+倍(?:
非捕获组[,;]*
先匹配,
或;
,然后匹配*
(?<ext>.[w*]+)
组ext的模式相同
)*
关闭非捕获组,并可选择重复以获取所有扩展
查看C#regex 101演示和C#演示。
例如
string pattern = @"b[fF]ilesb[^*()]*(?:([^()]*))?|*(?<ext>.[w*]+)(?:[,;]*(?<ext>.[w*]+))*";
string input = @"txt files `(*.txt)|*.txt|All files (*.*)|*.*`
Image Files`|*.jpg;*.jpeg;*.png;`
Excel Files `(*.xls, *.xlsx)|*.xls;*.xlsx|CSV Files (*.csv)|*.csv`";
var strings = Regex.Matches(input, pattern)
.SelectMany(m => m.Groups["ext"].Captures.Select(c => c.Value))
.ToArray()
.Distinct();
foreach (var s in strings)
{
Console.WriteLine(s);
}
输出
.txt
.*
.jpg
.jpeg
.png
.xls
.xlsx
.csv
另一种与数据格式无关的较短模式,匹配一个点和3或4个单词字符或星号,并在左侧断言一个点:
(?<=*).(?:w{3,4}b|*)
请参阅另一个regex演示。