我们使用零宽度正则表达式字符串来指定一串氨基酸符号(基本上是 AZ)中作为有效切割位点的位置。例如,蛋白水解酶胰蛋白酶在 K 或 R 之后切割,但在 P ( (?<=[KR])(?!P)
) 之后除外。我想将这些正则表达式转换为在该领域也很常见的“cut/no-cut”表示法。例如,胰蛋白酶在“KR”之后切割,没有切割“P”。我的第一次尝试适用于简单的情况:
// match zero or one regex term like (?<=[KR]) or (?<=K) or (?<![KR]) or (?<!K)
// followed by zero or one term like (?=[KR]) or (?=K) or (?![KR]) or (?!K)
boost::regex cutNoCutRegex("(?:\\(+\\?<([=!])(\\[[A-Z]+\\]|[A-Z])\\)+)?(?:\\(+\\?([=!])(\\[[A-Z]+\\]|[A-Z])\\)+)?");
如果没有 C++ 转义,那就是:
(?:\(+\?<([=!])(\[[A-Z]+\]|[A-Z])\)+)?(?:\(+\?([=!])(\[[A-Z]+\]|[A-Z])\)+)?
我想更改它以支持更复杂的正则表达式,例如多个字符、非捕获组、字符集、字符集中的范围、否定集和字符串的开始/结束:
(?<=K|R)
或(?<=(?:K)|(?:R))
或(?<=[^A-JL-QS-Z])
或(?<=^M|[KR])
这些额外的功能似乎会爆炸正则表达式的复杂性。我很确定我需要启用 Boost.Regex 的“实验性”BOOST_REGEX_MATCH_EXTRA 功能。有没有更好的方法来做我正在做的事情?我是否错过了零宽度正则表达式中的其他一些正则表达式可能性?
这是我对涵盖许多简单案例的现有代码的单元测试的伪代码。当“cut”字段对应于look-behind时“sense”成员是“C”,而当“cut”字段对应于look-ahead时是“N”。当前的 pepXMLSpecificity() 函数可以反转字符集,如果它会生成更短的列表。
struct PepXMLSpecificity { std::string cut, no_cut, sense; };
void unit_assert_equal(string expected, string actual);
"(?<=[QWERTY])(?=[QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("C", result.sense);
unit_assert_equal("QWERTY", result.cut);
unit_assert_equal("ABCDFGHIJKLMNOPSUVZ", result.no_cut);
"(?<![QWERTY])(?![QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("C", result.sense);
unit_assert_equal("ABCDFGHIJKLMNOPSUVZ", result.cut);
unit_assert_equal("QWERTY", result.no_cut);
"(?<=[QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("C", result.sense);
unit_assert_equal("QWERTY", result.cut);
unit_assert_equal("", result.no_cut);
"(?=[QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("N", result.sense);
unit_assert_equal("QWERTY", result.cut);
unit_assert_equal("", result.no_cut);
"(?<![QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("C", result.sense);
unit_assert_equal("ABCDFGHIJKLMNOPSUVZ", result.cut);
unit_assert_equal("", result.no_cut);
"(?![QWERTY])"
result = pepXMLSpecificity(ez);
unit_assert_equal("N", result.sense);
unit_assert_equal("ABCDFGHIJKLMNOPSUVZ", result.cut);
unit_assert_equal("", result.no_cut);
// the following tests aren't supported yet
"(?<=^M)|(?<=[KR])"
unit_assert_equal("N", result.sense);
unit_assert_equal("KR", result.cut); // the 'M' part is dropped
unit_assert_equal("", result.no_cut);
"(?<=K|R)"
unit_assert_equal("C", result.sense);
unit_assert_equal("KR", result.cut);
unit_assert_equal("", result.no_cut);
"(?<=(?:K)|(?:R))"
unit_assert_equal("C", result.sense);
unit_assert_equal("KR", result.cut);
unit_assert_equal("", result.no_cut);
"(?<=[^A-JL-QS-Z])(?!P)"
unit_assert_equal("C", result.sense);
unit_assert_equal("KR", result.cut);
unit_assert_equal("P", result.no_cut);