给定两个带*通配符的字符串,我想知道是否可以创建一个匹配两者的字符串。
例如,这两个是重叠的简单情况:
但所有这些都是如此:
是否发布了执行此操作的算法?或者可能是Windows中的实用程序功能或者我可以调用或复制的库?
答案 0 :(得分:6)
因为每个glob都可以写成正则表达式并且可以找到两个正则表达式的交集(除非它们不是真正的常规,但它们就是这种情况),你可以找到两个globs的交集。将它们转换为正则表达式,然后找到它们的交集。因此,您可以通过查找正则表达式的交集并检查它是否为空来查明两个globs是否相交。
然而,由于globs比正则表达式更受限制,因此更多更容易:
让我们调用两个球体g1和g2。它们与iff
相交haskell中的示例实现:
intersect g1 [] = all (== '*') g1
intersect [] g2 = all (== '*') g2
intersect g1@('*':t1) g2@(c2:t2) = intersect g1 t2 || intersect t1 g2
intersect g1@(c1:t1) g2@('*':t2) = intersect t1 g2 || intersect g1 t2
intersect (c1:t1) (c2:t2) = c1 == c2 && intersect t1 t2
如果globs包含很多通配符,这个算法并不是特别有效,但它很容易实现,因为你可能计划将它与文件名一起使用,我怀疑你的globs会超过1000个字符。
答案 1 :(得分:0)
对于它的价值,这里是来自sepp2k在C#中的答案的一个算法实现(我使用显式return true;
和return false;
调用,以及注释,用于算法可读性):
public static bool WildcardIntersect(string w1, string w2)
{
// if both are empty or contain wildcards
if ((string.IsNullOrEmpty(w1) || w1 == "*")
&& (string.IsNullOrEmpty(w2) || w2 == "*"))
return true;
// if either string is empty, return false
// we can do this because we know the other string MUST be non-empty and non-wildcard
if (string.IsNullOrEmpty(w1) || string.IsNullOrEmpty(w2))
return false;
char c1 = w1[0], // first character of wildcard string 1
c2 = w2[0]; // first character of wildcard string 2
string remain1 = w1.Substring(1), // remaining of wildcard string 1
remain2 = w2.Substring(1); // remaining of wildcard string 2
// if first letters match and remaining intersect
if ((c1 == c2 && WildcardIntersect(remain1, remain2))
// if either is a wildcard and either remaining intersects with the other whole
|| ((c1 == '*' || c2 == '*') && (WildcardIntersect(w1, remain2) || WildcardIntersect(remain1, w2))))
return true;
// else, no match, return false
return false;
}
答案 2 :(得分:0)
据我所知,你试着确定正则表达式是否与另一个正则表达式正交? 如果是这样,这不是一件小事。
以下是Theory.
的更多信息以下是解决方案:Java library.
用法:
/**
* @return true if the two regexes will never both match a given string
*/
public boolean isRegexOrthogonal( String regex1, String regex2 ) {
Automaton automaton1 = new RegExp(regex1).toAutomaton();
Automaton automaton2 = new RegExp(regex2).toAutomaton();
return automaton1.intersection(automaton2).isEmpty();
}
答案 3 :(得分:0)
这是sepp2k建议的算法的c ++实现,稍作修改:
bool intersect(const std::string& pattern1, const std::string& pattern2) {
if(pattern1.empty() && pattern2.empty()) return true;
if("*" == pattern1 || "*" == pattern2) return true;
if(pattern2.empty() && '*' == pattern1[0]) return true;
if(pattern1.empty() && '*' == pattern2[0]) return true;
if(pattern1.empty() || pattern2.empty()) return false;
char c1 = pattern1[0];
char c2 = pattern2[0];
string subPattern1 = pattern1.substr(1);
string subPattern2 = pattern2.substr(1);
if('*' == c1 && '*' == c2)
return intersect(pattern1, subPattern2) && intersect(subPattern1, pattern2);
if('*' == c1 && intersect(pattern1, subPattern2)
|| '*' == c2 && intersect(subPattern1, pattern2)
|| c1 == c2 && intersect(subPattern1, subPattern2)) {
return true;
}
return false;
}
答案 4 :(得分:0)
您可以在时间上线性解决图案长度的总和:
如果两个字符串都以非通配符开头或结尾,请检查它们是否匹配,直到一个模式命中了通配符(否则它们不匹配)。这将问题减少到至少一个模式以通配符开始并且至少一个模式以通配符结束的情况。如果两个模式都有通配符(在某处),则它们必须匹配:
否则,一个字符串(p1)没有通配符,而另一个字符串(p2)具有字符串s1,s2,...以通配符标点。因此,只需搜索p1中第一个出现的s1,然后搜索s2中的第一个后续出现(从p1中的匹配末尾开始),依此类推。如果找到所有字符串,则模式匹配,否则它们不匹配