C# 需要使用正则表达式对字符串执行通配符(*、?)搜索
我需要对字符串执行通配符(C# 需要使用正则表达式对字符串执行通配符(*、?)搜索,c#,.net,regex,string,wildcard,C#,.net,Regex,String,Wildcard,我需要对字符串执行通配符(*,?等)搜索。 这就是我所做的: string input = "Message"; string pattern = "d*"; Regex regex = new Regex(pattern, RegexOptions.IgnoreCase); if (regex.IsMatch(input)) { MessageBox.Show("Found"); } else { MessageBox.Show("Not Found"); } 用上面的代码
*
,?
等)搜索。
这就是我所做的:
string input = "Message";
string pattern = "d*";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(input))
{
MessageBox.Show("Found");
}
else
{
MessageBox.Show("Not Found");
}
用上面的代码“发现”块正在命中,但实际上不应该
如果我的模式是“e*”,那么只有“Found”应该命中
我的理解或要求是d*搜索应该找到包含“d”后跟任何字符的文本
我是否应该将模式更改为“d.*”和“e.*”?在.NET中是否有对通配符的支持,它在使用Regex类时在内部执行此操作?
d*
意味着它应该匹配零个或多个“d
”字符。因此,任何字符串都是有效匹配项。试试d+
为了支持通配符模式,我将用RegEx等价物替换通配符。像*
变成*
和?
变成?
。然后,上面的表达式变成d.*
来自:
因此类似于
foo*.xls?
的内容将被转换为^foo.*.xls.$
全局表达式d*
的正确正则表达式公式是^d
,这意味着匹配以d
开头的任何内容
string input = "Message";
string pattern = @"^d";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
(在这种情况下,
@
引号是不必要的,但这是一种良好的做法,因为许多正则表达式使用需要单独使用的反斜杠转义,并且它还向读者表明此字符串是特殊的)。您需要将通配符表达式转换为正则表达式。例如:
private bool WildcardMatch(String s, String wildcard, bool case_sensitive)
{
// Replace the * with an .* and the ? with a dot. Put ^ at the
// beginning and a $ at the end
String pattern = "^" + Regex.Escape(wildcard).Replace(@"\*", ".*").Replace(@"\?", ".") + "$";
// Now, run the Regex as you already know
Regex regex;
if(case_sensitive)
regex = new Regex(pattern);
else
regex = new Regex(pattern, RegexOptions.IgnoreCase);
return(regex.IsMatch(s));
}
必须在输入通配符模式中转义特殊正则表达式符号(例如模式
*.txt
将相当于^.*.txt$
)
因此斜杠、大括号和许多特殊符号必须替换为
@“\”+s
,其中s
-特殊正则表达式符号。Windows和*nux对通配符的处理方式不同<代码>*、?
和
是由Windows以非常复杂的方式处理的,一个人的存在或位置会改变另一个人的含义。虽然*nux保持简单,但它所做的只是一个简单的模式匹配。除此之外,Windows为0或1个字符匹配?
,Linux为1个字符匹配
我没有找到关于这个问题的权威性文件,以下是我在Windows8/XP(命令行,dir
command,以及Directory.GetFiles
方法也使用相同的规则)和Ubuntu服务器12.04.1(ls
command)上经过几天的测试得出的结论。我做了几十个常见和不常见的案例,虽然也有很多失败的案例
Gabe目前的答案类似于*nux。如果您还想要一个Windows样式的,并且愿意接受其缺陷,那么它就是:
/// <summary>
/// <para>Tests if a file name matches the given wildcard pattern, uses the same rule as shell commands.</para>
/// </summary>
/// <param name="fileName">The file name to test, without folder.</param>
/// <param name="pattern">A wildcard pattern which can use char * to match any amount of characters; or char ? to match one character.</param>
/// <param name="unixStyle">If true, use the *nix style wildcard rules; otherwise use windows style rules.</param>
/// <returns>true if the file name matches the pattern, false otherwise.</returns>
public static bool MatchesWildcard(this string fileName, string pattern, bool unixStyle)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (pattern == null)
throw new ArgumentNullException("pattern");
if (unixStyle)
return WildcardMatchesUnixStyle(pattern, fileName);
return WildcardMatchesWindowsStyle(fileName, pattern);
}
private static bool WildcardMatchesWindowsStyle(string fileName, string pattern)
{
var dotdot = pattern.IndexOf("..", StringComparison.Ordinal);
if (dotdot >= 0)
{
for (var i = dotdot; i < pattern.Length; i++)
if (pattern[i] != '.')
return false;
}
var normalized = Regex.Replace(pattern, @"\.+$", "");
var endsWithDot = normalized.Length != pattern.Length;
var endWeight = 0;
if (endsWithDot)
{
var lastNonWildcard = normalized.Length - 1;
for (; lastNonWildcard >= 0; lastNonWildcard--)
{
var c = normalized[lastNonWildcard];
if (c == '*')
endWeight += short.MaxValue;
else if (c == '?')
endWeight += 1;
else
break;
}
if (endWeight > 0)
normalized = normalized.Substring(0, lastNonWildcard + 1);
}
var endsWithWildcardDot = endWeight > 0;
var endsWithDotWildcardDot = endsWithWildcardDot && normalized.EndsWith(".");
if (endsWithDotWildcardDot)
normalized = normalized.Substring(0, normalized.Length - 1);
normalized = Regex.Replace(normalized, @"(?!^)(\.\*)+$", @".*");
var escaped = Regex.Escape(normalized);
string head, tail;
if (endsWithDotWildcardDot)
{
head = "^" + escaped;
tail = @"(\.[^.]{0," + endWeight + "})?$";
}
else if (endsWithWildcardDot)
{
head = "^" + escaped;
tail = "[^.]{0," + endWeight + "}$";
}
else
{
head = "^" + escaped;
tail = "$";
}
if (head.EndsWith(@"\.\*") && head.Length > 5)
{
head = head.Substring(0, head.Length - 4);
tail = @"(\..*)?" + tail;
}
var regex = head.Replace(@"\*", ".*").Replace(@"\?", "[^.]?") + tail;
return Regex.IsMatch(fileName, regex, RegexOptions.IgnoreCase);
}
private static bool WildcardMatchesUnixStyle(string pattern, string text)
{
var regex = "^" + Regex.Escape(pattern)
.Replace("\\*", ".*")
.Replace("\\?", ".")
+ "$";
return Regex.IsMatch(text, regex);
}
//
///测试文件名是否与给定的通配符模式匹配,使用与shell命令相同的规则。
///
///要测试的文件名,不带文件夹。
///一种通配符模式,可以使用char*匹配任意数量的字符;还是炭?匹配一个字符。
///如果为true,则使用*nix样式的通配符规则;否则,请使用windows样式规则。
///如果文件名与模式匹配,则为true,否则为false。
公共静态bool匹配通配符(此字符串文件名、字符串模式、bool unixStyle)
{
如果(文件名==null)
抛出新的ArgumentNullException(“文件名”);
if(pattern==null)
抛出新的异常(“模式”);
if(unixStyle)
返回通配符匹配unixstyle(模式、文件名);
返回通配符匹配WindowsStyle(文件名、模式);
}
私有静态布尔通配符匹配WindowsStyle(字符串文件名、字符串模式)
{
var dotdot=pattern.IndexOf(“..”,StringComparison.Ordinal);
如果(点>=0)
{
for(var i=dotdot;i=0;lastNonWildcard--)
{
var c=标准化的[lastNonWildcard];
如果(c=='*')
endWeight+=short.MaxValue;
else如果(c=='?')
端重+=1;
其他的
打破
}
如果(端重>0)
normalized=normalized.Substring(0,lastNonWildcard+1);
}
var ENDSWILTWILDCARDDOT=端重>0;
var endsWithDotWildcardDot=endsWithWildcardDot&&normalized.EndsWith(“.”);
if(endsWithDotWildcardDot)
normalized=normalized.Substring(0,normalized.Length-1);
normalized=Regex.Replace(normalized,@“(?!^)(\.\*)+$”,@“*”;
var-Escape=Regex.Escape(标准化);
线头、线尾;
if(endsWithDotWildcardDot)
{
head=“^”+逃逸;
尾=@“(\.[^.]{0,+endWeight+”})?$”;
}
else if(endsWithWildcardDot)
{
head=“^”+逃逸;
tail=“[^.]{0,”+endWeight+“}$”;
}
其他的
{
head=“^”+逃逸;
tail=“$”;
}
if(head.EndsWith(@“\.\*”)&&head.Length>5)
{
头部=头部子字符串(0,头部长度-4);
尾=@“(\..*)?”+尾;
}
var regex=head.Replace(@“\*”,“*”).Replace(@“\?”,“[^.]?”)+tail;
返回Regex.IsMatch(文件名,Regex,RegexOptions.IgnoreCase);
}
私有静态bool通配符matchesunixstyle(字符串模式,字符串文本)
{
var regex=“^”+regex.Escape(模式)
.替换(“\\*”,“*”)
/// <summary>
/// <para>Tests if a file name matches the given wildcard pattern, uses the same rule as shell commands.</para>
/// </summary>
/// <param name="fileName">The file name to test, without folder.</param>
/// <param name="pattern">A wildcard pattern which can use char * to match any amount of characters; or char ? to match one character.</param>
/// <param name="unixStyle">If true, use the *nix style wildcard rules; otherwise use windows style rules.</param>
/// <returns>true if the file name matches the pattern, false otherwise.</returns>
public static bool MatchesWildcard(this string fileName, string pattern, bool unixStyle)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (pattern == null)
throw new ArgumentNullException("pattern");
if (unixStyle)
return WildcardMatchesUnixStyle(pattern, fileName);
return WildcardMatchesWindowsStyle(fileName, pattern);
}
private static bool WildcardMatchesWindowsStyle(string fileName, string pattern)
{
var dotdot = pattern.IndexOf("..", StringComparison.Ordinal);
if (dotdot >= 0)
{
for (var i = dotdot; i < pattern.Length; i++)
if (pattern[i] != '.')
return false;
}
var normalized = Regex.Replace(pattern, @"\.+$", "");
var endsWithDot = normalized.Length != pattern.Length;
var endWeight = 0;
if (endsWithDot)
{
var lastNonWildcard = normalized.Length - 1;
for (; lastNonWildcard >= 0; lastNonWildcard--)
{
var c = normalized[lastNonWildcard];
if (c == '*')
endWeight += short.MaxValue;
else if (c == '?')
endWeight += 1;
else
break;
}
if (endWeight > 0)
normalized = normalized.Substring(0, lastNonWildcard + 1);
}
var endsWithWildcardDot = endWeight > 0;
var endsWithDotWildcardDot = endsWithWildcardDot && normalized.EndsWith(".");
if (endsWithDotWildcardDot)
normalized = normalized.Substring(0, normalized.Length - 1);
normalized = Regex.Replace(normalized, @"(?!^)(\.\*)+$", @".*");
var escaped = Regex.Escape(normalized);
string head, tail;
if (endsWithDotWildcardDot)
{
head = "^" + escaped;
tail = @"(\.[^.]{0," + endWeight + "})?$";
}
else if (endsWithWildcardDot)
{
head = "^" + escaped;
tail = "[^.]{0," + endWeight + "}$";
}
else
{
head = "^" + escaped;
tail = "$";
}
if (head.EndsWith(@"\.\*") && head.Length > 5)
{
head = head.Substring(0, head.Length - 4);
tail = @"(\..*)?" + tail;
}
var regex = head.Replace(@"\*", ".*").Replace(@"\?", "[^.]?") + tail;
return Regex.IsMatch(fileName, regex, RegexOptions.IgnoreCase);
}
private static bool WildcardMatchesUnixStyle(string pattern, string text)
{
var regex = "^" + Regex.Escape(pattern)
.Replace("\\*", ".*")
.Replace("\\?", ".")
+ "$";
return Regex.IsMatch(text, regex);
}
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
if (Operators.LikeString("This is just a test", "*just*", CompareMethod.Text))
{
Console.WriteLine("This matched!");
}
public string WildcardToRegex(string pattern)
{
string result= Regex.Escape(pattern).
Replace(@"\*", ".+?").
Replace(@"\?", ".");
if (result.EndsWith(".+?"))
{
result = result.Remove(result.Length - 3, 3);
result += ".*";
}
return result;
}
public static String WildCardToRegular(this String value)
{
return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
}
public static bool WildCardMatch(this String value,string pattern,bool ignoreCase = true)
{
if (ignoreCase)
return Regex.IsMatch(value, WildCardToRegular(pattern), RegexOptions.IgnoreCase);
return Regex.IsMatch(value, WildCardToRegular(pattern));
}
string pattern = "file.*";
var isMatched = "file.doc".WildCardMatch(pattern)
string xlsxFile = "file.xlsx"
var isMatched = xlsxFile.WildCardMatch(pattern)
public class Wildcard
{
private readonly string _pattern;
public Wildcard(string pattern)
{
_pattern = pattern;
}
public static bool Match(string value, string pattern)
{
int start = -1;
int end = -1;
return Match(value, pattern, ref start, ref end);
}
public static bool Match(string value, string pattern, char[] toLowerTable)
{
int start = -1;
int end = -1;
return Match(value, pattern, ref start, ref end, toLowerTable);
}
public static bool Match(string value, string pattern, ref int start, ref int end)
{
return new Wildcard(pattern).IsMatch(value, ref start, ref end);
}
public static bool Match(string value, string pattern, ref int start, ref int end, char[] toLowerTable)
{
return new Wildcard(pattern).IsMatch(value, ref start, ref end, toLowerTable);
}
public bool IsMatch(string str)
{
int start = -1;
int end = -1;
return IsMatch(str, ref start, ref end);
}
public bool IsMatch(string str, char[] toLowerTable)
{
int start = -1;
int end = -1;
return IsMatch(str, ref start, ref end, toLowerTable);
}
public bool IsMatch(string str, ref int start, ref int end)
{
if (_pattern.Length == 0) return false;
int pindex = 0;
int sindex = 0;
int pattern_len = _pattern.Length;
int str_len = str.Length;
start = -1;
while (true)
{
bool star = false;
if (_pattern[pindex] == '*')
{
star = true;
do
{
pindex++;
}
while (pindex < pattern_len && _pattern[pindex] == '*');
}
end = sindex;
int i;
while (true)
{
int si = 0;
bool breakLoops = false;
for (i = 0; pindex + i < pattern_len && _pattern[pindex + i] != '*'; i++)
{
si = sindex + i;
if (si == str_len)
{
return false;
}
if (str[si] == _pattern[pindex + i])
{
continue;
}
if (si == str_len)
{
return false;
}
if (_pattern[pindex + i] == '?' && str[si] != '.')
{
continue;
}
breakLoops = true;
break;
}
if (breakLoops)
{
if (!star)
{
return false;
}
sindex++;
if (si == str_len)
{
return false;
}
}
else
{
if (start == -1)
{
start = sindex;
}
if (pindex + i < pattern_len && _pattern[pindex + i] == '*')
{
break;
}
if (sindex + i == str_len)
{
if (end <= start)
{
end = str_len;
}
return true;
}
if (i != 0 && _pattern[pindex + i - 1] == '*')
{
return true;
}
if (!star)
{
return false;
}
sindex++;
}
}
sindex += i;
pindex += i;
if (start == -1)
{
start = sindex;
}
}
}
public bool IsMatch(string str, ref int start, ref int end, char[] toLowerTable)
{
if (_pattern.Length == 0) return false;
int pindex = 0;
int sindex = 0;
int pattern_len = _pattern.Length;
int str_len = str.Length;
start = -1;
while (true)
{
bool star = false;
if (_pattern[pindex] == '*')
{
star = true;
do
{
pindex++;
}
while (pindex < pattern_len && _pattern[pindex] == '*');
}
end = sindex;
int i;
while (true)
{
int si = 0;
bool breakLoops = false;
for (i = 0; pindex + i < pattern_len && _pattern[pindex + i] != '*'; i++)
{
si = sindex + i;
if (si == str_len)
{
return false;
}
char c = toLowerTable[str[si]];
if (c == _pattern[pindex + i])
{
continue;
}
if (si == str_len)
{
return false;
}
if (_pattern[pindex + i] == '?' && c != '.')
{
continue;
}
breakLoops = true;
break;
}
if (breakLoops)
{
if (!star)
{
return false;
}
sindex++;
if (si == str_len)
{
return false;
}
}
else
{
if (start == -1)
{
start = sindex;
}
if (pindex + i < pattern_len && _pattern[pindex + i] == '*')
{
break;
}
if (sindex + i == str_len)
{
if (end <= start)
{
end = str_len;
}
return true;
}
if (i != 0 && _pattern[pindex + i - 1] == '*')
{
return true;
}
if (!star)
{
return false;
}
sindex++;
continue;
}
}
sindex += i;
pindex += i;
if (start == -1)
{
start = sindex;
}
}
}
}
var ismatch2 = Wildcard.Match("xmlfsdfsd", "xml*");