【发布时间】:2010-10-31 13:34:02
【问题描述】:
有谁知道 .NET 中是否有与 Windows API 函数 PathMatchSpec() 等效的功能?
【问题讨论】:
有谁知道 .NET 中是否有与 Windows API 函数 PathMatchSpec() 等效的功能?
【问题讨论】:
我不知道 .NET 内置的方法,但是用正则表达式复制是微不足道的:
public static bool PathMatchSpec(String path, String spec)
{
String specAsRegex = Regex.Escape(spec).Replace("\\*", ".*").Replace("\\?", ".") + "$";
return Regex.IsMatch(path, specAsRegex);
}
显然,这假定引用了 System.Text.RegularExpressions 命名空间。如果您要使用相同的规范执行此操作,您也可以缓存正则表达式。
编辑添加:P/Invoke 确实是一个选项,但 PathMatchSpec 的签名表明它需要一个 ANSI 字符串,因此每次调用都会发生字符集转换。如果你走那条路,请记住这一点。在那种情况下,PathMatchSpecEx 可能会更好。
【讨论】:
如果您无法使用正则表达式获得功能(我相信是这种情况),如何通过 PInvoke 使用 PathMatchSpec()?
http://www.pinvoke.net/default.aspx/shlwapi/PathMatchSpec.html
【讨论】:
您可以尝试 How to implement glob in C# ,如果需要,当然还有PInvoke route。
【讨论】:
简而言之...我不知道...但也许这可以帮助您(注意,比您想要的要长一点,但它对我很有帮助):
sealed public class WildcardMatch
{
private static Regex wildcardFinder = new Regex(@"(?<wildcards>\?+|\*+)", RegexOptions.Compiled | RegexOptions.Singleline);
private Regex wildcardRegex;
public WildcardMatch(string wildcardFormat) : this(wildcardFormat, false) { }
public WildcardMatch(string wildcardFormat, bool ignoreCase)
{
if (wildcardFormat == null)
throw new ArgumentNullException("wildcardFormat");
StringBuilder patternBuilder = new StringBuilder("^");
MatchCollection matches = this.wildcardFinder.Matches(wildcardFormat);
string[] split = this.wildcardFinder.Split(wildcardFormat);
for (int ix = 0; ix < split.Length; ix++)
{
// Even indexes are literal text, odd indexes correspond to matches
if (ix % 2 == 0)
patternBuilder.Append(Regex.Escape(split[ix]));
else
{
// Matches must be substituted with Regex control characters
string wildcards = matches[ix / 2].Groups["wildcards"].Value;
if (wildcards.StartsWith("*", StringComparison.Ordinal))
patternBuilder.Append("(.*)");
else
patternBuilder.AppendFormat(CultureInfo.InvariantCulture, "({0})", wildcards.Replace('?', '.'));
}
}
patternBuilder.Append("$");
this.wildcardRegex = new Regex(
patternBuilder.ToString(),
RegexOptions.Singleline | (ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None));
}
public bool IsMatch(string value)
{
if (value == null)
return false;
return this.wildcardRegex.IsMatch(value);
}
public IEnumerable<string> ExtractMatches(string value)
{
if (value == null)
yield break;
Match match = this.wildcardRegex.Match(value);
if (!match.Success)
yield break;
for (int ix = 1; ix < match.Groups.Count; ix++)
yield return match.Groups[ix].Value;
}
}
【讨论】: