尝试使用正则表达式 \/\*(.|\n)*?\*\/ 来选择每个 C 多行注释,但它在 SED 中不起作用

尝试使用正则表达式 \/\*(.|\n)*?\*\/ 来选择每个 C 多行注释,但它在 SED 中不起作用

我需要匹配 C 风格的多行注释,例如。

#include <stdio.h>

int main()
{
    // this is a dummy function
    float sum = 0;
    // testing the sed commands
    
    int x = 6; // single-line comment
    x = x + 5;
    
    char y = 'n'; /* end of c  *
    file */
}

我需要删除所有多行注释。

所以我用了sed s/\/\*\(.\|\n\)*\?\*\///,但是不起作用。我尝试/%:替换,s%\/\*\(.\|\n\)*\?\*\/%%但它仍然不起作用。

任何人都可以帮忙指挥这个正则表达式\/\*(.|\n)*?\*\/操作sed吗?

答案1

Sed 处理由尾随换行符 ( \n) 字符定义的“记录”(行)。这意味着您无法匹配过去的 a,\n因为就其而言sed,the\n是记录的结尾。在 GNU 中sed,您可以通过使用-zslurp 文件并将整个文件视为单个记录来解决这个问题(除非您的文件\0中有 NULL ( ) ,在这种情况下,每个文件\0都会定义一条记录):

$ sed -zE 's|/\*.*\n.*\*/||' file.c 
#include <stdio.h>

int main()
{
    // this is a dummy function
    float sum = 0;
    // testing the sed commands
    
    int x = 6; // single-line comment
    x = x + 5;
    
    char y = 'n'; 
}

但是,如果同一个文件中有多个多行注释,则此操作将会失败,因为sed无法进行非贪婪匹配,因此它将始终尝试查找最长可能的匹配,这意味着它将从第一个/*到最后一个匹配*/。因此,使用可以进行非贪婪匹配的工具,例如perl

$ perl -0777 -pe 's|/\*.*?\n.*?\*/||gs' file.c 
#include <stdio.h>

int main()
{
    // this is a dummy function
    float sum = 0;
    // testing the sed commands
    
    int x = 6; // single-line comment
    x = x + 5;
    
    char y = 'n'; 
}

但是,如果您只有单行注释/* */,则此操作将会失败。我能想到的最安全的方法是忘记尝试使用正则表达式来执行此操作,而是编写一个小脚本来记录打开和关闭注释标签的计数并相应地进行删除。

/*另一个问题是带有or的字符串*/也会破坏它。例如,如果你有类似的东西怎么办:

char foo [ ] = "A comment starts with /*";

归根结底,唯一安全的方法是这个答案经过埃德·莫顿它使用 C 预处理器:

如果这是在 C 文件中,那么您必须将 C 预处理器与其他工具结合使用,以暂时禁用特定的预处理器功能,例如扩展 #defines 或 #includes,所有其他方法在边缘情况下都会失败。这适用于所有情况:

[ $# -eq 2 ] && arg="$1" || arg=""
eval file="\$$#"
sed 's/a/aA/g; s/__/aB/g; s/#/aC/g' "$file" |
          gcc -P -E $arg - |
          sed 's/aC/#/g; s/aB/__/g; s/aA/a/g'

将其放入 shell 脚本中,并使用要解析的文件名来调用它,可以选择添加“-ansi”等标志作为前缀,以指定要应用的 C 标准。

https://stackoverflow.com/a/35708616/1745001了解详情。

相关内容