我有数千个日志文件 - 都非常大。其中之一将有我正在寻找的 IP 地址。我知道它很可能发生在文件顶部附近。我可以:
head -n 500 *.log | fgrep myip
我会看到“是”,它位于日志文件之一中。我如何确定是哪一个?由于文件大小的原因,不可能对所有文件的完整内容 (fgrep myip *.log) 进行 Grep 操作。
答案1
你只需 awk 就可以逃脱:
awk -v ip=127.0.0.1 'substr($0, ip) > 0 {print FILENAME ": " $0} FNR > 500 {nextfile}' *.log
如果在当前行中找到 IP,我们将打印它和文件名。如果当前文件 ( FNR
) 的当前行号变得 > 500,我们将跳到下一个文件。
答案2
像这样的事情应该有帮助。
find . -iname "*.log" -print0 | xargs -0 -i{} bash -c 'echo "»»»File Name: {}«««"; head -n 500 {} | fgrep -B 501 myip'
它将生成一长串文件名,然后是最多 500 行找到的数据,然后是一长串文件名。您想要的文件名是紧邻一长串数据之前的文件名。
答案3
find -name \*.log -print0 |
xargs -0 sh -c 'for i; do head -n 500 $i | fgrep -q myip && echo $i; done
这将找到所有以 结尾的文件名.log
,并将该列表提供给xargs
.和通常用于使用空字节来终止文件名,以保护包含空格的文件名(空字节永远不能在文件名中使用,因此是安全的分隔符)-print0
。xargs -0
xargs
将运行后面给出的命令xargs
及其参数,并使用一次命令调用中适合的文件名。在本例中,给出的命令是sh
(shell),并且该 shell 被给予一个小的 shell 脚本来运行。
shell脚本基本上是:
for i; do
head -n 500 $i | fgrep -q myip && echo $i
done
该for i
部分循环遍历给 shell 的所有参数,即所有文件名。对于每个文件名,它会获取前 500 行,并搜索给定的字符串。fgrep -q
意味着 fgrep 一旦找到字符串就停止;如果找到该字符串,则给出退出状态“成功”,否则给出“失败”。最后,这&& echo $i
意味着如果前面的命令具有“成功”状态,则执行回显,这意味着如果找到字符串则显示文件名。
答案4
我会:
- 循环遍历所有文件
- 抓取前 500 行
- 看看 IP 是否在这些行中
- 如果是,则打印文件名并结束循环
作为代码:
for f in ./*
do
head -n 500 "$f" | grep -qF myip && { printf "Found in: $f"; break; }
done
将其替换myip
为您要查找的 IP。您可以创建一个函数(或 shell 脚本),将所需的 IP 作为参数进行搜索:
findlogip ()
{
for f in ./*;
do
head -n 500 "$f" | grep -qF "$1" && {
printf "Found in: $f\n";
break
};
done
}
作为罗艾玛 评论,您可能需要小心搜索的 IP,以免意外匹配不同的 IP(示例中为 10.55.33.6,但匹配 110.55.33.68)。使用 GNU grep (假设,鉴于操作系统标记),您可以用标记包围给定的 IP 地址\b
:
...
head -n 500 "$f" | grep -q "\b$1\b" && ...
...
您删除-F
(固定字符串)grep 选项,因为表达式不再是“固定”表达式,而是正则表达式。