我有一个特殊要求,我的正则表达式模式将在运行时确定,例如我有一个日期并希望对其进行检查,或者基本上mm-dd-yyyy
我将把模式作为一个数字和一个字母来输入表达式可以是任何东西。我们可以编写任何适用于这种要求的正则表达式吗?mm/dd/yyyy
d.mm.yyyy
NN-NN-TTTT
N
T
我的表单看起来像http://jsfiddle.net/E2EHZ/中显示的数据将匹配对应于文本框中指定的模式
T
- 字母
N
- 数字
A
- 字母数字
我有一个特殊要求,我的正则表达式模式将在运行时确定,例如我有一个日期并希望对其进行检查,或者基本上mm-dd-yyyy
我将把模式作为一个数字和一个字母来输入表达式可以是任何东西。我们可以编写任何适用于这种要求的正则表达式吗?mm/dd/yyyy
d.mm.yyyy
NN-NN-TTTT
N
T
我的表单看起来像http://jsfiddle.net/E2EHZ/中显示的数据将匹配对应于文本框中指定的模式
T
- 字母
N
- 数字
A
- 字母数字
所以基本上你会让你的用户输入一个包含T
,N
或A
作为占位符的模式,其他字符需要在两者之间进行字面匹配?如果是这样,那么这很容易:只需用适当的字符类替换占位符,引用其余部分(因此正则表达式元字符被转义)并将结果用作正则表达式。
首先逃避一切不是 A
,N
或T
。如何做到这一点因语言而异,但基本上你会用[^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 + "$";
}
生成的正则表达式会更长一些,因为上面的代码不会对相同的标记使用重复。