给定两个带有*通配符的字符串,我想知道是否可以创建一个可以匹配这两个字符串的字符串。
例如,这两个字符串是重叠的简单情况:
- Hello*World
- Hel*
但所有这些都是简单情况:
- *.csv
- reports*.csv
- reportsdump.csv
是否有已发布的算法来执行此操作?或者在Windows中是否有实用程序函数或库可以调用或复制?
给定两个带有*通配符的字符串,我想知道是否可以创建一个可以匹配这两个字符串的字符串。
例如,这两个字符串是重叠的简单情况:
但所有这些都是简单情况:
是否有已发布的算法来执行此操作?或者在Windows中是否有实用程序函数或库可以调用或复制?
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
如果通配符很多,这个算法并不特别高效,但是它很容易实现,而且由于你可能计划在文件名中使用它,我怀疑你不会有超过1000个字符的通配符。
就算只是一点点价值,这里提供了一个 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;
}
我理解你想确定一个正则表达式是否与另一个正则表达式正交吗?如果是这样,这是非常不平凡的问题。
关于理论,这里有更多信息。
这里有解决方案:Java库。
用法:
/**
* @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();
}
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;
}