我试图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版本。
答案 0 :(得分:1)
您提供的命令使用grep 4次。您可以使用单个grep命令跳过注释行:
grep -v "^ *\(--\|#\)" "pathtofile"
要打印包含word1
的文件名,请像这样使用cut
:
grep -Hv "^ *\(--\|#\)" filenames | grep "word1" | cut -d: -f1
要跳过内联注释,请使用sed
:
sed "s/\(.*\)\(--\|#\).*/\1/g" inputfile
样本输入:
word1
word2
-word3 # inline comment
#comment1
--comment2
#comment3
输出:
word1
word2
-word3
答案 1 :(得分:0)
实际上,如果您尝试解析编程语言的源文件,则最好使用适当的解析器。这是一种尝试将代码重构为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] }' {} +
这有一个明显的缺陷,即如果编程语言允许在引号的字符串中使用#
或--
并且不将其视为注释,则脚本将执行错误的操作。
您的脚本中没有单词边界,因此我也没有放在任何单词边界中。这意味着如果word="dog"
,则它将按此顺序打印包含三个相邻字母d-o-g的任何字符串,即使在子字符串匹配(例如“ doggone”或“内生”)中也是如此。如果这不是您想要的,则可以添加单词边界标记-如果您具有GNU Awk,则可以在脚本开头说BEGIN { word = "\\<" word "\\> }
;否则,您可以添加单词边界标记。或see here.
将密钥添加到数组中并仅在密钥不在数组中时才打印密钥的技术是实现uniq
的常用方法。如果find
返回的文件太多,以至于它将运行多个awk
实例,则此操作将失败-这将由内核ARG_MAX
的值控制。>