解决方案:

解决方案:

很多时候,当手动查找文件时,会有太多注释让您的眼睛呆滞,您开始希望有一种方法可以让它只显示那些没有注释的行。

有没有办法用 cat 或其他工具跳过评论?我猜有一种方法,它涉及正则表达式。我希望它只是显示而不是实际删除任何行等。

注释采用 # 的形式,我使用 zsh 作为我的 xterm。

答案1

好吧,这取决于你的评论是什么意思。如果只是没有 a 的行,#则简单:

grep -v '#'

可能就足够了(但这会像echo '#'注释一样调用行)。如果注释行是行开始#那么你可能需要:

grep -v '^#'

如果注释行是#在一些可选空格之后开始的行,那么您可以使用:

grep -v '^ *#'

如果评论格式完全不同,这个答案对你没有帮助。

答案2

仅 grep 永远无法删除所有注释(或仅删除注释),因为 grep 不理解它正在经历的语言。要了解什么是评论,什么不是评论,您需要词法分析器理解那种特定的语言。

关于如何删除特定编程语言中的所有注释,有几个答案。我将在这里添加两个例子。

为了C乔什·李的回答认为:

gcc -fpreprocessed -dD -E test.c

它运行预处理器但保留宏。

为了Python unutbu 的回答(我自己进行了一些小修改)使用 tokenize 编写了一个小型词法分析器:

import tokenize
import io
import sys

def nocomment(s):
    result = []
    g = tokenize.generate_tokens(io.BytesIO(s).readline)  
    for toknum, tokval, _, _, _  in g:
        # print(toknum,tokval)
        if toknum != tokenize.COMMENT:
            result.append((toknum, tokval))
    return tokenize.untokenize(result)

print(nocomment(sys.stdin.read()))

然后,您可以为每种编程语言编写其中一个并使用案例。假设 python 词法分析器被调用remove-comments.py

#!/bin/sh
case "$1" in
  *.py)
    remove-comments.py < "$1"
    break
    ;;
  *.c|*.C|*.cc)
    gcc -fpreprocessed -dD -E "$1"
    break
    ;;
  *)
    echo I do not know how to remove comments from $1, sorry
    break
    ;;
esac

给脚本命名并添加词法分析器对于您需要/使用的语言。这应该是一个或多或少稳健的设计,用于从不同文件类型中删除注释。 (使用file文件名而不是大小写也会更可靠)。

答案3

grep -v "^#" your_file | grep -v "^$" | less

删除以“#”开头的行并删除空行,然后将结果发送到less以获得更好的显示。

答案4

正如上面的评论中提到的,“评论”在您的用例中采用什么格式会产生影响。不过,对于某些情况,这可能就足够了,无需创建脚本。

解决方案:

阅读问题表明您已经使用grep已经来搜索文件,因此通过另一个管道将其传输grep;像这样:

grep your_pattern your_file | grep --perl-regexp --invert-match '(?:^;)|(?:^\s*/\*.*\*/)|(?:^\s*#|//|\*)'

什么没有被困:

这仍然允许行 或 在行的其他地方有“触发”字符,在末尾有注释,如echo "Hello World" # another comment,或者是多行注释的一部分(除非下面的解释中指出)。

如果将其用作 grep 的后置过滤器,那么这些限制应该可以忽略不计,因为大多数评论仍会被过滤掉,并且您将不再担心“您的眼睛呆滞”。

说明:

共有三种模式,您可以根据需要进行修改以适合您的用例。第一个(?:^;)捕获以字符开头的行;。必须是第一个,没有空格。第二个捕获以 、或开头的行,catches lines that begin with the `/* ... */` comment style, with or without leading white space. The third无论是否有前导空格。最后一个模式有助于捕获多行注释中的行,其中常见的样式是运行一列将第一行和最后一行连接在一起。例如:#//**/* ... */*

/************
 *
 * This is my
 * multi-line
 * comment.
 *
 ************/

每个模式周围的符号(? ... )使它们成为“非捕获”模式,希望能够提高速度并减少资源消耗。 grep 的参数-Pv告诉它使用 Perl 正则表达式规则--perl-regexp,该规则允许非捕获分组并允许|交替运算符工作,这两者在 CLI grep 中都不起作用。 grep 手册页确实警告 -P 选项是实验性的,因此在系统中依赖它之前请先进行测试。告诉反转匹配,返回不符合模式的行--invert-matchgrep这些可以组合起来,并缩短为-vP相反。

使用它作为正常的后置过滤器的原因grep有三个。首先,您可以进行正常的 grep 操作,并且仅在遇到输出中注释过多的问题时才添加使用此功能的额外工作。 (更少的打字和使用的资源更少。)其次,您可能已经开发了常用的模式以及随之而来的习惯,并且增加它们的复杂性可能会破坏它们。在不必要的情况下添加更多工作来调试模式是浪费工作。第三,它根本不能很好地处理多行注释,但是如果您已经根据需要对文件进行了 grep,那么它会从结果中删除大部分(如果不是全部)注释,并达到您的目的。

相关内容