我有几个要分析的apache访问文件。我正在尝试通过以下方式使用grep:
grep -v term_to_grep apache_access_log
我有几个要grep的字词,因此我正在按如下方式传递每个grep动作:
grep -v term_to_grep_1 apache_access_log | grep -v term_to_grep_2 | grep -v term_to_grep_3 | grep -v term_to_grep_n > apache_access_log_cleaned
直到这里,我的基本脚本都能按预期工作!但是我有很多apache访问日志,我不想对每个文件都这样做。我已经开始编写bash脚本,但到目前为止我无法使其正常工作。这是我的尝试:
for logs in ./access_logs/*;
do
cat $logs | grep -v term_to_grep | grep -v term_to_grep_2 | grep -v term_to_grep_3 | grep -v term_to_grep_n > $logs_clean
done;
有人可以指出我做错了什么吗?
答案 0 :(得分:2)
如果您有一个变量,并在其名称后附加_clean
,则这是一个新变量,而不是旧变量的值附加了_clean
。要解决此问题,请使用花括号:
$ var=file.log
$ echo "<$var>"
<file.log>
$ echo "<$var_clean>"
<>
$ echo "<${var}_clean>"
<file.log_clean>
没有它,您的管道将尝试重定向到空字符串,这将导致错误。请注意,"$file"_clean
也可以使用。
对于管道,您可以将其合并为一个grep命令:
grep -Ev 'term_to_grep|term_to_grep_2|term_to_grep_3|term_to_grep_n' "$logs" > "${logs}_clean"
不需要cat
,只需一次调用grep。
或者您可以将所有条款粘贴到文件中
$ cat excludes
term_to_grep_1
term_to_grep_2
term_to_grep_3
term_to_grep_n
,然后使用-f
选项:
grep -vf excludes "$logs" > "${logs}_clean"
如果您的术语是字符串而不是正则表达式,则可以使用-F
(“固定字符串”)来加快速度:
grep -vFf excludes "$logs" > "${logs}_clean"
不过,我认为GNU grep会自行为您检查。
答案 1 :(得分:1)
您要遍历多个文件,但是在循环中您会不断覆盖结果文件,因此该文件将只包含最后一个文件中的最后一个结果。
您不需要循环,请改用此循环:
egrep -v 'term_to_grep|term_to_grep_2|term_to_grep_3' ./access_logs/* > "$logs_clean"
请注意,使用set -eEuCo pipefail
启动Bash脚本总是有帮助的。这会捕获最常见的错误-当您尝试破坏$logs_clean
文件时,它会因错误而停止。