Linux面试必问---如何在一个大文件中找到某关键字,学会解答思路走到哪儿都不怕!

在很多面试中,只要求职者写了熟悉linux的时候,基本所有面试官都会问的一个问题就是

服务器上有一个很大的文件,如何从里面找到某个关键字?

首先我们不管是作为一个测试还是开发人员,分析问题一点要从多个方面入手,并且如果可能的话先别急着回答,先想并提问题,敢于质疑,才是一个好测试:

  • 需要找到所有匹配的关键字还是只需要找到第一个匹配的关键字?
  • 只找某个关键字就可以了吗?需要关键字的前后几行来协助分析吗?
  • 关键字的匹配是否需要考虑大小写?
  • 是否需要在匹配结果中同时显示关键字所在的行号?
  • 这个大文件高于服务器内存了吗?

解决方案

1.关键字的匹配是否需要考虑大小写?

#若不需要考虑大小写,可以grep -i
grep -i "关键字" /path/filename

第一个是一个最基础的回答,但是记住,grep只会返回符合条件的行,并不会返回上下文信息

2.需要找到所有匹配的关键字还是只需要找到第一个匹配的关键字?

#对于匹配几个关键字,可以通过grep -m来实现,-m 后面的数字为我们要返回的关键字数
grep -m 10000 "关键字" /path/filename
#结合一下一二点就是,既不区分大小写,又仅返回前1024个
grep -i -m 1024 "关键字" /path/filename

3.是否需要在匹配结果中同时显示关键字所在的行号?

#显示关键字所在的行号,可以grep -n处理
grep -n "关键字" /path/filename

4.只找某个关键字就可以了吗?需要关键字的前后几行来协助分析吗?

#需要前后几行的话又很多种方法
1.通过grep -C(大写)后面跟数字,来搜索关键字的上下num行
grep -C5 "关键字" /path/filename  #搜索关键字的上下5行

2.通过grep命令后加more实现
grep "关键字" /path/filename | more  #more仅可向后翻页

3.通过grep命令后加less实现
grep "关键字" /path/filename | less  #less支持向前向后翻页

4.使用awk命令,其中 NR 表示当前行号,$0 表示整行内容,这条命令会把包含关键字的行及其行号打印出来。
awk '/关键字/{print NR" "$0} ' /path/filename

5.使用more或者less
如less ./logs,进入页面后再:后面输入/+需要搜索等关键字,这样就可以了

5.文件过大怎么办?

如果文件过大,在搜索关键字时可能会面临内存不足的问题,我们的解决方案可以为:
1.将文件划分为多个小文件,逐个文件进行搜索。这种方式需要考虑如何划分文件,以及如何对搜索结果进行合并。实现过程如下:

#以下命令将把/path/filename划分为1000MB大小的文件,并且将分割后的文件存储到/path/to/outputdir目录中,文件名以prefix开头(如果不指定前缀,默认以x开头)
 - split -b 1000M  /path/filename /path/to/outputdir/prefix
#以下命令将搜索/path/to/outputdir/目录中所有文件中包含"关键字"的行,并将结果保存到/path/to/resultfilename文件中。
 - grep "关键字" /path/to/outputdir/* > /path/to/resultfile
 
2.使用流式处理技术,在读取文件时只保留必要的数据,而不是将整个文件读取到内存中。例如,使用管道操作符将多个命令连接起来,构成一个流处理管道。

#将一个大文件按行读取,并找到包含指定关键字的行,并输出该行及其前5行和后5行:
grep -n "关键字" /path/failname| awk -F ':' '{print $1}' | sed -e 's/$/ -5p/' -e 's/^/\'':/+1' /path/failname | sh

这个命令的流程是:
1.使用 grep -n "关键字" /path/failname 命令在文件 /path/failname 中搜索关键字,并显示关键字所在的行号。其中 -n 选项表示显示行号。
2.使用管道将上一步的输出传递给 awk -F ':' '{print $1}' 命令。这个命令的作用是将每一行的输出只保留行号部分,并去掉冒号和关键字的部分。
3.使用管道将上一步的输出传递给 sed 命令。这个命令的作用是对每一个行号进行处理,使得能够显示关键字所在行前面的 5 行内容和后面的内容。具体来说,命令 -e 's/$/ -5p/' 将每一个行号结尾添加 -5p,表示显示该行前面的 5 行内容;命令 -e 's/^/\'':/+1' 将每一个行号开头添加 :' +1,表示显示该行后面的内容。
4.最后使用管道将上一步的输出传递给 sh 命令,执行显示操作。

以上命令使用了流式处理技术,不会将整个大文件读取到内存中,只保留必要的数据逐行处理。

你可能感兴趣的:(小问题解决,linux,面试,服务器)