正则表达式查询(运行时可自定义)

时间:2012-08-03 06:49:55

标签: java regex

我有一个特殊要求,我的正则表达式模式将在运行时确定,表示我有一个日期,并希望根据mm-dd-yyyymm/dd/yyyyd.mm.yyyy进行检查基本上我会将模式作为NN-NN-TTTT提供,其中N表示数字,T表示字母,表达式可以是任何字母。我们可以编写任何适用于此类要求的正则表达式吗?

我的表单看起来像http://jsfiddle.net/E2EHZ/中显示的数据将匹配对应于文本框中指定的模式

T - 信
N - 数字
A - Alphanum

1 个答案:

答案 0 :(得分:3)

所以基本上你会让你的用户输入一个包含TNA的模式作为占位符,其他字符需要在两者之间进行字面匹配?如果是这样,那么它很容易:只需用适当的字符类替换占位符,引用其余的(因此转义正则表达式元字符)并将结果用作正则表达式。

ANT的首次逃避。如何执行此操作因语言而异,但基本上您可以使用转义版本的匹配替换[^ANT]+。在C#中,它可能如下所示:

Regex.Replace(s, "[^ANT]+", m => Regex.Escape(m.Value));

或在Java中:

s.replaceAll("[^ANT]+", "\\Q$0\\E"

要执行的翻译很简单:

T → [a-zA-Z]
N → [0-9]
A → [0-9a-zA-Z]

即,假设仅使用ASCII。对于Unicode,您可能需要

T → \p{L}
N → \p{Nd}
A → [\p{L}\p{Nd}]

代替。另请注意,如果执行简单的字符串替换,则需要首先使用ASCII版本替换A,然后首先将N替换为Unicode变体,以避免在后续结果中替换它。

最后,如果您想匹配完整的字符串,您可能希望在字符串前加^,并在后缀$

C#中的示例实现(具有微小的优化):

string CreateRegex(string pattern) {
  string result = Regex.Replace(pattern, "[^ANT]+", m => Regex.Escape(m.Value));
  result = Regex.Replace(result, "A+", m => "[0-9a-zA-Z]" + (m.Length > 1 ? "{"+m.Length+"}" : ""));
  result = Regex.Replace(result, "T+", m => "[a-zA-Z]" + (m.Length > 1 ? "{"+m.Length+"}" : ""));
  result = Regex.Replace(result, "N+", m => "[0-9]" + (m.Length > 1 ? "{"+m.Length+"}" : ""));
  return "^" + result + "$";
}

例如导致以下结果:

NN-NN-TTTT → ^[0-9]{2}-[0-9]{2}-[a-zA-Z]{4}$
*(@&#^(&%(@  AA-AA-NN-TTTTTTTT lreglig → \*\(@&\#\^\(&%\(@\ \ [0-9a-zA-Z]{2}-[0-9a-zA-Z]{2}-[0-9]{2}-[a-zA-Z]{8}\ lreglig

或者在Java中(没有说优化,因为我无法弄清楚如何使用函数作为替换):

String createRegex(String pattern) {
  String result = pattern.replaceAll("[^ANT]+", "\\Q$0\\E");
  result = result.replaceAll("A", "[0-9a-zA-Z]");
  result = result.replaceAll("T", "[a-zA-Z]");
  result = result.replaceAll("N", "[0-9]");
  return "^" + result + "$";
}

由此产生的正则表达式会更长一些,因为上面的代码不会对相同的标记使用重复。