0

我有一个特殊要求,我的正则表达式模式将在运行时确定,例如我有一个日期并希望对其进行检查,或者基本上mm-dd-yyyy我将把模式作为一个数字和一个字母来输入表达式可以是任何东西。我们可以编写任何适用于这种要求的正则表达式吗?mm/dd/yyyyd.mm.yyyyNN-NN-TTTTNT

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

T- 字母
N- 数字
A- 字母数字

4

1 回答 1

3

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

首先逃避一切不是 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}]

反而。另请注意,如果您执行简单的字符串替换,您需要先替换A为 ASCII 版本,然后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 + "$";
}

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

于 2012-08-03T08:12:13.750 回答