RegEx:抓住引号之间的所有文本(包括嵌套的文本),除非在注释行中(以//开头)

时间:2019-04-17 16:39:44

标签: regex

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

代码示例:

// 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");

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

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

1 个答案:

答案 0 :(得分:0)

关于输入文件的类型没有写任何东西,因此我假设使用C源代码文件。

我建议使用文本编辑器UltraEdit(使用
Boost C++ Perl regular expression library

^(?:(?!//|"|').)*(["'])(?!\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: %s\n",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: %s\n

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

搜索字符串的说明:

  • ^ ...从一行的开头开始搜索。
    这是为什么不能在不在行注释中的行上将此表达式的第二,第三,...字符串匹配的主要原因。

  • (?:(?!//|"|').)* ...使用非标记组搜索零个或多个字符,这些字符不是换行符,下一个既没有//也没有"也没有{ {1}}已使用包含OR表达式的否定超前验证进行了验证。
    该表达式负责忽略由于行{p>

  • 而在一行中找到'之后的所有内容 接下来必须找到
  • // ... (["'])",并将找到的字符标记为反向引用。

  • ' ...但是,只有当下一个字符与忽略空字符串的字符不同时,匹配才为正。

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

  • ' ...一个非标记组,用于查找反斜杠和字符串开头的字符,或者查找非贪婪换行字符的任何字符一次或多次。
    此表达式匹配目标字符串。

  • (?:\\\1|.)+? ...与任何不是换行符的字符匹配时,应在下一个字符(正向向前)处停止,该字符与未使用反斜杠转义的引用字符相同,而不是字符串开头,匹配此引号字符。

用于匹配行注释外部的第一个非空字符串,该行的两侧都有定界符:

(?=\1)

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

  1. 将整个C源代码文件的内容复制到一个新文件中。
  2. 使用搜索表达式删除所有未嵌套的块注释和所有行注释的新文件:
    ^(?:(?!//|"|').)*\K(["'])(?!\1)(?:\\\1|.)+?\1
    替换字符串是一个空字符串。
    注意:字符串中的^[\t ]*//.*[\r\n]+|[\t ]*/\*[\s\S]+?\*/[\r\n]*|[\t ]*//.*$也会由OR表达式的第三部分解释为行注释的开头,尽管这不正确。
  3. 用作搜索字符串//来查找实际上所有非空字符串,并且在每个字符串的两侧也都匹配字符串定界字符。

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