我是我们Qt。我有一个文本字符串,我专门查找函数调用xyz.set_name()
,我想捕获该调用的最后一次出现,但如果包含它的行以#
开头,则将其取反。到目前为止,我得到了与函数调用匹配的regex,但我不知道如何否定#
匹配的行,也不知道如何捕获最后一次出现的行,不知道为什么所有匹配都放在一个捕获组中。
[().wd]+.set_name()s*
这就是我想要它做的
abc.set_name() // match
# abc.set_name() // don't match
xyz.set_name() // match and capture this one
更新以获得更多澄清:
当用qDebug 打印出来时,我的文本读起来是这样的
Hellonx=y*2nabc.set_name() n#xyz.set_name()
它是一个以n
为换行符的长字符串。
更新:用于测试的较长测试字符串。我已经尝试了所有建议的正则表达式,但它们都不起作用。不知道缺了什么。https://regex101.com/r/vXpXIA/1
更新2:Scratch我的第一次更新,n
是qDebug()
,在使用regex时不需要考虑它。
如果您只想匹配与模式匹配的最后一行
^[a-z]+.set_name()
可以使用正则表达式。
(?smi)^[a-z]+.set_name()(?!.*^[a-z]+.set_name())
为了简单起见,我使用了字符类[a-z]
。可以根据需要进行更改。在这个问题中,它是[().wd]
,可以简化为[().w]
。
请注意,由于感兴趣的子字符串正在匹配,因此捕获它也没有意义。最后一行之前的一行以'#'
开头的事实并不相关。所有重要的是线条是否匹配指定的图案。
启动发动机!
PCRE正则表达式引擎执行以下操作。
(?smi) : set single-line, multi-line and case-indifferent
modes
^ : match the beginning of a line
[a-z]+.set_name() : match 1+ chars in the char class, followed
by '.set_name()'
(?! : begin negative-lookahead
.*^[a-z]+.set_name() : match 0+ chars (including newlines), the
beginning of a line, 1+ letters, '.set_name()'
) : end negative lookahead
回想一下,单行模式使.
与换行符匹配,而多行模式使^
和$
与行的开头和结尾(而不是字符串的开头和末尾(匹配。
您需要regex前瞻运算符(如果您的regex引擎支持(。这会奏效的。
(?(?=^[^#])(^s*[a-zA-Z]+.set_name())|z^)
解释:
(?(?=patt)then|else)
-Regex if else构造,如果Regex与给定模式patt
匹配,则then
匹配,否则else
匹配patt
=^[^#]
-在线路开始时,没有#
则部分-如果
patt
为true,则^s*[a-zA-Z]*.set_name()
匹配后面跟有<something>.set_name()
的任意数量的空白,其中something
是变量名。else-part-如果
patt
为false,则匹配行开始之前的z的z^
,这是不可能的。
Edit:刚刚意识到变量名中可以有数字(但不能以数字开头(。在这种情况下,改进的regex(未测试(
(?(?=^[^#])(^s*[a-zA-Z]+[a-zA-Zd]*.set_name())|z^)
编辑:由于字符串中也有换行符,因此它与问题中的问题描述不匹配。尽管如此,只要标记字符串就足够简单了。
只需根据新行将字符串拆分即可。
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
int main()
{
std::istringstream isr;
isr.str("I am Johnn today is n#abc.set_name()n");
std::string tok;
std::vector<std::string> vs;
while(std::getline(isr, tok))
{
std::cout << tok << std::endl;
vs.push_back(tok);
}
for (auto r_it = vs.rbegin(); r_it != vs.rend(); ++r_it)
{
std::cout << *r_it << std::endl;
// if match then break from loop
}
}
您可以使用
(?s).*n(?!h*#)h*([w().]+.set_name())
请参阅regex演示,您的匹配项在第1组详细信息:
(?s)
-DOTALL模式打开,.
现在匹配任何字符.*
-尽可能多的任何零个或多个字符n(?!h*#)
-一个换行符,后面没有0个或多个水平空白,然后是一个#
字符h*
-0+水平空白([w().]+.set_name())
-捕获组1:[w().]+
-1个或多个字字符,)
、(
或.
.set_name()
—.set_name()
字符串