正则表达式:抓取引号之间的所有文本(包括嵌套),除非在注释行中(以 // 开头)



我正在尝试将一个表达式放在一起,该表达式将抓取引号(单引号或双引号)之间的文本,包括嵌套引号中的文本,但会忽略注释中的文本,因此除非该行以//开头。

代码示例:

// this is a "comment" and should be ignored
//this is also a 'comment' and should be ignored
printf("This is text meant to be "captured", and can include any type of character");
printf("This is the same as above, only with 'different' nested quotes");

这对于从文件中提取可翻译内容非常有用。

到目前为止,我已经设法使用^((?!//).)*从导入中排除注释行,并["'](.+)["']提取引号之间的文本,但我无法将其组合到单个表达式上。 按顺序运行它们也不起作用,我认为是因为第一个表达式中的贪婪量词。

没有写任何关于输入文件类型的内容,所以我假设 C 源代码文件。

我建议遵循使用文本编辑器UltraEdit测试的正则表达式,该编辑器使用
Boost C++ Perl正则表达式库。

^(?:(?!//|"|').)*(["'])(?!1)K(?:\1|.)+?(?=1)

它匹配一行上的第一个单引号或双引号字符串。同一行上的其他字符串被Perl语法中的正则表达式搜索字符串忽略,这不是最佳的。

它忽略行注释中的单引号或双引号字符串,这些字符串以//独立的行注释开头,该行注释位于没有前导空格/制表符的行的开头,或代码后行中的其他位置。

它还忽略空字符串,如""''.如果一行包含第一个""'',第二个包含单引号或双引号的非空字符串,则也会忽略非空字符串。这不是最佳的。

字符串分隔字符在匹配字符串的两边不匹配。

字符串分隔字符必须使用反斜杠字符进行转义,才能被此搜索表达式解释为字符串中的文字字符。所讨论示例中的第一个printf肯定会在 C 编译器编译时导致语法错误。

由于预处理器宏,编译器不会忽略块注释中的字符串,编译器也不会忽略代码中的字符串。

例:

// This is a "comment" and should be ignored.
//This is also a 'comment' which should be ignored.
printf("This is text meant to be "captured", and can include any type of character.n");  // But " must be escaped with a backslash.
printf("This is the same as above, only with 'different' nested quotes.n");
putchar('I');
putchar(''');
printf(""); printf("m thinking.");  // First printf is not very useful.
printf(""OK!"");
printf("Hello"); printf(" world!n");
printf("%d file%s found.n",iFileCount,((iFileCount != 1) ? "s" : "");
printf("Result is: %sn",sText);  // sText is "success" or "failure".
return iReturnCode; // 0 ... "success", 1 ... "error"

搜索表达式与此示例匹配:

This is text meant to be "captured", and can include any type of character.n
This is the same as above, only with 'different' nested quotes.n
I
'
"OK!"
Hello
%d file%s found.n
Result is: %sn

因此,它不会在运行 C 代码示例时找到所有非空字符串输出。

搜索字符串说明:

  • ^......从行首开始搜索。
    这就是为什么无法与第二个,第三个,...行上的字符串不在行注释中。

  • (?:(?!//|"|').)*......使用非标记组搜索零个或多个不是换行符的字符,接下来既没有//换行符,也没有",也没有'使用包含 OR 表达式的否定前瞻进行验证。
    此表达式负责忽略//在一行中找到后的所有内容,因为

  • (["'])...... 接下来必须找到"',并且找到的字符标记为反向引用。

  • (?!1)......但仅当下一个字符不是忽略空字符串的同一字符时,匹配才是正的。

  • K......将$0的开始位置重置为当前文本位置:换句话说,K左侧的所有内容都将"保留",并且不构成正则表达式匹配的一部分。因此,从行首到非空字符串开头的"'匹配的所有内容都不再匹配(选择)。

  • (?:\1|.)+?......非标记组,用于查找反斜杠和字符串开头的字符或任何不是换行符的字符非贪婪一次或多次。
    此表达式与感兴趣的字符串匹配。

  • (?=1)......匹配任何不是换行符的字符都应在下一个字符(正面展望)上停止,该字符与字符串开头的引号字符不符,未与字符串开头的反斜杠转义,而不匹配此引号字符。

对于将行外的第一个非空字符串与两侧的分隔符匹配:

^(?:(?!//|"|').)*K(["'])(?!1)(?:\1|.)+?1

如何在注释之外获取真正的所有非空字符串?

  1. 将整个 C 源代码文件的内容复制到新文件中。
  2. 在新文件中删除所有非嵌套块注释和所有带有搜索表达式的行注释:^[t ]*//.*[rn]+|[t ]*/*[sS]+?*/[rn]*|[t ]*//.*$替换

    字符串为空字符串。
    注意:字符串内的//被OR表达式的第三部分解释为行注释的开头,尽管这是不正确的。
  3. 用作搜索字符串(["'])(?!1)(?:\1|.)+?1查找真正所有非空字符串,并匹配每个字符串两侧的字符串分隔字符。

最好是用 C 编写的程序解析 C 源代码文件以获取非空字符串,因为这样的程序可以更好地找出什么是行注释,什么是块注释,即使在包含嵌套块注释的源代码文件上也是如此,什么是非空字符串。好吧,也可以让 C 编译器只预处理项目的 C 源代码文件,并在预处理后生成输出文件,并删除所有行和块注释,并在这些预处理文件中搜索非空字符串。

最新更新