我将使用啥代码将类似 SQL 的表达式即时转换为正则表达式?
Posted
技术标签:
【中文标题】我将使用啥代码将类似 SQL 的表达式即时转换为正则表达式?【英文标题】:What code would I use to convert a SQL like expression to a regex on the fly?我将使用什么代码将类似 SQL 的表达式即时转换为正则表达式? 【发布时间】:2010-09-08 00:06:13 【问题描述】:我希望将类似 SQL 的语句即时转换为等效的正则表达式,即
LIKE '%this%'
LIKE 'Sm_th'
LIKE '[C-P]arsen'
最好的方法是什么?
附:我希望在 .Net Framework (C#) 上执行此操作。
【问题讨论】:
【参考方案1】:以下 Regex 在 MatchEvaluator
委托的帮助下将类似 SQL 的模式转换为 Regex 模式。它正确处理方括号块并转义特殊的正则表达式字符。
string regexPattern = "^" + Regex.Replace(
likePattern,
@"[%_]|\[[^]]*\]|[^%_[]+",
match =>
if (match.Value == "%")
return ".*";
if (match.Value == "_")
return ".";
if (match.Value.StartsWith("[") && match.Value.EndsWith("]"))
return match.Value;
return Regex.Escape(match.Value);
) + "$";
【讨论】:
如果您使用此代码生成的正则表达式,“hello%”将匹配“Say hello”,这是不正确的。 好点@JimBerg,我已经添加了开始/结束锚点。 我使用了您的答案,但对 % 何时位于开头或结尾或两者兼而有之进行了特殊检查。 SQL 表达式与正则表达式相反。如果你想要'%hello%',它只转换为'hello'。 '你好'翻译成'^你好$'。 'hello%' 是 '^hello' 而 '%hello' 是 'hello$'。我不知道是否有人曾经在中间使用 % ,例如 'hello%world' ,它将匹配以 hello 开头并以 world 结尾的任何内容。您的答案似乎确实可以正确处理。很高兴看到您在 9 年后仍然活跃。 :-)【参考方案2】:除了@Nathan-Baulch 的解决方案之外,您还可以使用下面的代码来处理使用LIKE '!%' ESCAPE '!'
语法定义了自定义转义字符的情况。
public Regex ConvertSqlLikeToDotNetRegex(string regex, char? likeEscape = null)
var pattern = string.Format(@"
0[%_]|
[%_]|
\[[^]]*\]|
[^%_[0]+
", likeEscape);
var regexPattern = Regex.Replace(
regex,
pattern,
ConvertWildcardsAndEscapedCharacters,
RegexOptions.IgnorePatternWhitespace);
regexPattern = "^" + regexPattern + "$";
return new Regex(regexPattern,
!m_CaseSensitive ? RegexOptions.IgnoreCase : RegexOptions.None);
private string ConvertWildcardsAndEscapedCharacters(Match match)
// Wildcards
switch (match.Value)
case "%":
return ".*";
case "_":
return ".";
// Remove SQL defined escape characters from C# regex
if (StartsWithEscapeCharacter(match.Value, likeEscape))
return match.Value.Remove(0, 1);
// Pass anything contained in []s straight through
// (These have the same behaviour in SQL LIKE Regex and C# Regex)
if (StartsAndEndsWithSquareBrackets(match.Value))
return match.Value;
return Regex.Escape(match.Value);
private static bool StartsAndEndsWithSquareBrackets(string text)
return text.StartsWith("[", StringComparison.Ordinal) &&
text.EndsWith("]", StringComparison.Ordinal);
private bool StartsWithEscapeCharacter(string text, char? likeEscape)
return (likeEscape != null) &&
text.StartsWith(likeEscape.ToString(), StringComparison.Ordinal);
【讨论】:
【参考方案3】:从你上面的例子中,我会这样攻击它(我说的是笼统的说法,因为我不懂 C#):
用 LIKE '...' 将其分开,将 ... 部分放入一个数组中。 将未转义的 % 符号替换为 .*,将下划线替换为 .,在这种情况下,[CP]arsen 直接转换为正则表达式。
用管道将数组片段重新连接在一起,并将结果用括号和标准正则表达式位包裹起来。
结果是:
/^(.*this.*|Sm.th|[C-P]arsen)$/
这里最重要的是要警惕所有可以转义数据的方式,以及哪些通配符转换为哪些正则表达式。
% becomes .*
_ becomes .
【讨论】:
需要注意的一点是,如果类似 sql 的模式包含 \,那么您想在正则表达式中转义它。 Regex.Escape 在这里会有所帮助【参考方案4】:我找到了一个名为 Regexp::Wildcards 的 Perl 模块。您可以尝试移植它或尝试 Perl.NET。我有一种感觉,你也可以自己写一些东西。
【讨论】:
以上是关于我将使用啥代码将类似 SQL 的表达式即时转换为正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章