【问题标题】:Grep to exclude comment like # and -- with trailing spaces and within lineGrep 排除注释,如 # 和 -- 带有尾随空格和行内
【发布时间】:2018-08-22 03:41:21
【问题描述】:

我试图在文件中 grep 包含 # 和 -- 作为注释的单词。我使用的命令是 grep "^[^#]" -H -R -I "pathtofile" | grep "^[^--]" | grep -in ${1} | awk -F : ' { print $2 } ' | uniq) 这将打印特定单词的文件名。但是,如果有这样的一行

        --test_specific_word_test test

上面的代码会将上面的代码视为不跳过它。这种情况也适用于注释与var=1 --comment等代码一致的地方。

我应该先使用 sed 删除注释行还是只使用 grep。

缺点是我有大量文件要搜索,而 GNU grep 是 2.0,我无法升级 grep 版本,因为我没有权限。

【问题讨论】:

  • 真的不清楚你在问什么。 grep '^[^--]' 看起来像是个错误——你的意思是 grep -ve '--' 吗?无论如何,如果您在此管道中使用 Awk,您不妨将其全部重构为 Awk 脚本(然后,您拥有哪个 grep 版本并不重要。顺便说一句,仅 2.0 并没有透露任何内容-- 你的意思是你有 GNU grep 2.0?)
  • @tripleee。该语句用于行首并在括号中否定 -- 。我误解了我的解释吗?我怎样才能使用 awk 来完成这个?我需要它来打印文件名 awk 能做到吗?是的,我有 GNU grep 2.0
  • 它寻找一个不是-- 的字符,这显然是多余的。您是否期望不在行首的 -- 被此过滤掉?
  • 如果没有更详细的要求,您的管道在做什么或做错了什么并不明显。但是例如grep -nv 'regex' | grep 'poo' | awk '{ print $2 }'可以重构为awk '!/regex/ && /poo/ { print FNR ":" $2 }'
  • 请记住,[--][-] 完全相同——括号定义了一个 字符类,它只匹配一个字符——哪一组字符一个字符可以取决于这些括号的内容。

标签: bash sed grep


【解决方案1】:

您提供的命令使用了 grep 4 次。您可以使用单个 grep 命令跳过注释行:

grep -v "^ *\(--\|#\)" "pathtofile"

要打印包含word1 的文件名,请使用cut,如下所示:

grep -Hv "^ *\(--\|#\)" filenames | grep "word1" | cut -d: -f1

要跳过内联 cmets,请使用 sed:

sed "s/\(.*\)\(--\|#\).*/\1/g" inputfile

示例输入:

word1
   word2
  -word3 # inline comment
   #comment1
   --comment2
 #comment3

输出:

word1
   word2
  -word3

【讨论】:

  • 这仍然不能解决 var=2 -- comment 的情况,尽管我仍然不假装完全理解 OP 希望如何解决这个问题,或者还有什么其他极端情况。
【解决方案2】:

如果实际上您正在尝试解析一种编程语言的源文件,您最好使用适当的解析器。这是将您的代码重构为 Awk 脚本的尝试,对脚本实际上应该做什么有几个猜测。

find pathtofile -type f -exec awk -v word="$1" -F : '
    # this doesn't reimplement grep -I though
    { sub("(#|--).*", "") } # remove comments
    tolower($0) ~ tolower(word) && !($2 in a) { print FILENAME ":" FNR ":" $2; a[$2] }' {} +

这有一个明显的缺陷,如果编程语言允许 #-- 在带引号的字符串中并且不将它们视为 cmets,则脚本会做错事。

你的剧本中没有字边界,所以我的也没有。这意味着如果 word="dog" 则它将按此顺序打印包含三个相邻字母 d-o-g 的任何字符串,即使在“doggone”或“endogenous”之类的子字符串匹配中也是如此。如果这不是你想要的,你可以添加单词边界标记——如果你有 GNU Awk,你可以在脚本的开头说BEGIN { word = "\\<" word "\\> };或see here.

将键添加到数组并仅在该键不在数组中时才打印该键的技术是实现uniq 的常用方法。如果find 返回的文件太多以至于最终会运行多个awk 实例,这将失败——这将由内核的ARG_MAX 的值控制。

【讨论】:

    猜你喜欢
    • 2018-07-22
    • 2015-07-06
    • 1970-01-01
    • 2017-05-31
    • 2012-02-28
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多