循环从Apache日志文件中过滤掉行

时间:2019-11-14 13:55:26

标签: linux bash loops grep

我有几个要分析的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;

有人可以指出我做错了什么吗?

2 个答案:

答案 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文件时,它会因错误而停止。