有没有办法在文本文件/脚本中只显示未注释的行?

shi*_*ish 26 grep zsh text-processing regular-expression cat

很多时候,当手动搜索文件时,有太多的评论让您眼花缭乱,您开始希望有一种方法可以让您只显示那些没有评论的行。

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

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

Ste*_*uch 24

嗯,这取决于你所说的评论是什么意思。如果只是没有一个的行,#那么一个简单的:

grep -v '#'
Run Code Online (Sandbox Code Playgroud)

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

grep -v '^#'
Run Code Online (Sandbox Code Playgroud)

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

grep -v '^ *#'
Run Code Online (Sandbox Code Playgroud)

如果评论格式完全不同,这个答案将无济于事。

  • `grep -v '#'` 是不够的,因为它会忽略像 `echo "#"` 这样的行。`grep -v '^#'` 也是不够的,因为评论可以出现在任何时候,比如 `echo "hello world" # 这是一条评论` (2认同)
  • 只需尝试 `grep -v '^ *#' 来仅匹配第一个非空格字符为 `#` 的行。 (2认同)

gro*_*mal 14

仅使用 grepping 永远无法删除所有注释(或仅删除注释),因为 grep 不了解它所使用的语言。要了解什么是注释,什么不是注释,您需要一个能够理解该特定语言的词法分析器。

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

对于C ,乔希·李( Josh Lee )的回答认为:

gcc -fpreprocessed -dD -E test.c
Run Code Online (Sandbox Code Playgroud)

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

对于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()))
Run Code Online (Sandbox Code Playgroud)

然后,您可以为每种编程语言编写其中一个并使用案例。假设调用了 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
Run Code Online (Sandbox Code Playgroud)

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


小智 11

grep -v "^#" your_file | grep -v "^$" | less
Run Code Online (Sandbox Code Playgroud)

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