2

我们使用零宽度正则表达式字符串来指定一串氨基酸符号(基本上是 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);
4

1 回答 1

1

据我了解,情况是,您有一个现有正则表达式库,当应用于氨基酸序列的常见字符串表示时,可以识别蛋白水解酶的可能切点。

您希望自动生成正则表达式隐含的切点的标准文本描述。

观察:

  • 您不需要能够解析任意正则表达式,您只需要能够解析您在库中实际拥有的案例。

  • 您不一定需要解析所有这些。难度特别大的,只要数量不多,就可以用手踢掉。

真的,我认为您需要执行以下操作。

  1. pepXMLSpecificity 需要返回一个或多个描述,即 a vector<struct PepXMLSpecificity>,因为可以编写正则表达式来组合任意正则表达式 cf。jpalacek 的评论。

  2. 你应该处理你的正则表达式库的实际内容,从常见的情况开始,然后逐渐减少,然后为每种常见的正则表达式添加特殊情况,直到你把它们全部搞定(或者至少让你的老板满意)。

于 2012-01-19T15:17:09.963 回答