c++ - 使用正则表达式解析零宽度正则表达式

标签 c++ regex pcre boost-regex

我们使用零宽度正则表达式字符串来指定氨基酸符号字符串(基本上是 A-Z)中有效切割位点的位置。例如,蛋白水解 enzyme 胰蛋白 enzyme 在 K 或 R 之后裂解,除非后跟 P ((?<=[KR])(?!P))。我想将这些正则表达式转换为在该领域也很常见的“剪切/不剪切”符号。例如,胰蛋白 enzyme 在“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”字段对应于后视时,“sense”成员为“C”,当“cut”字段对应于前视时,“sense”成员为“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);

最佳答案

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

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

观察:

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

  • 您不一定需要解析所有这些。特别难的可以踢出来手工做,只要数量不多。

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

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

  2. 您应该处理您的正则表达式库的实际内容,从常见情况开始逐步深入,然后为每种常见类型的正则表达式添加特殊情况,直到您获得全部(或至少足够多)让你的老板满意)。

关于c++ - 使用正则表达式解析零宽度正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8899343/

相关文章:

php - preg_replace() 如何理解 $replacement 参数中的 '${1}1,$3'?

java - 从动态库调用 jni 时 JVM 堆内存不足

c++ - 更新 Makefile 以适应当今的标准

c++ - 'texture2D' : function is removed in Forward Compatibile context

Javascript:如何用匹配的组搜索和替换多个项目?

c++ - 正则表达式驱动的 while 循环没有正确循环

regex - Vim 正则表达式中的 Pcre (*SKIP)?

regex - PCRE:回溯中不允许反向引用?

c++ - 如何打印结构 vector ?是不是没有保存数据?

javascript - JS 正则表达式 : select only links (a) with attr