如何在Linux中读取文件中特定的一行?
在使用Linux shell时,读取文本文件通常是一个重要的操作。有时,我们可能只对读取文件中的特定一行感兴趣。
我们将看看从文件中获取特定文本的不同方法。
实际问题
让我们来看一个例子。
假设我们有一个名为“test.txt”的文件:
$ nl test.txt 1 This is line 1, I don't have any interesting data. 2 This is line 2, I don't have any interesting data. 3 This is line 3, I don't have any interesting data. 4 This is line 4, I don't have any interesting data. 5 This is line 5, interesting data: Linux is awesome! 6 This is line 6, I don't have any interesting data. 7 This is line 7, I don't have any interesting data.
我们使用nl函数显示带有行号的文本文件内容。
我们知道前四行包含一些有趣的信息。因此,我们只想读取第五行。
在Linux命令行中有很多方法可以做到这一点。在本指南中,我们将介绍四种不同的方法:
使用Bash命令
使用sed命令
使用awk命令
使用head和tail命令
让我们来看一些例子。
使用Bash命令
为了解决这个问题,我们需要编写一个名为getLine的shell脚本。
$ cat getLine.sh #!/bin/bash FILE="$1" LINE_NO=$2 i=0 while read line; do i=$(( i + 1 ) test $i = $LINE_NO && echo "$line"; done <"$FILE"
上面的shell脚本接受两个参数:文件名和目标行号。
基本上,它包含一个段落。我们首先将$i的值设置为零。然后我们检查当前行是否与我们目标的行(第十行)匹配。如果是,我们将$i加1。否则,我们将打印当前行。
命令
$ ./getLine.sh test.txt 5
输出
This is line 5, interesting data: Linux is awesome!
结果显示我们的脚本运行成功。
如果我们仔细阅读文本,我们可能会改进它。
我们在循环中检查字符串中的每一个字符,即使我们已经找到并打印了我们想要的字符。实际上,我们可能在找到我们想要的内容之前处理了大量数据。但是,让我们坚持这个例子!我们的示例输入只有七行。然而在现实世界中,您的输入可能包含数百万行。
因此,如果我们能够在找到正确的行后退出循环,那就太好了。所以,让我们稍微修改一下脚本:
$ cat getLine2.sh #!/bin/bash FILE="$1" LINE_NO=$2 i=0 while read line; do i=$(( i + 1 )) case $i in $LINE_NO) echo "$line"; break;; esac done <"$FILE"
我们使用case语句在找到我们想要的行时停止循环。让我们看看它是否有效:
命令
$ ./getLine2.sh test.txt 5
输出
This is line 5, interesting data: Linux is awesome!
我们通过使用一些bash脚本解决了这个问题。
使用sed命令
sed命令非常擅长解决这类问题。这里有两个简洁的sed单行命令可以完成这项工作。
命令
$ sed '5!d' test.txt
输出
This is line 5, interesting data: Linux is awesome!
命令
$ sed -n '5p' test.txt
输出
This is line 5, interesting data: Linux is awesome!
要删除目录中除第五行(也是唯一一行)以外的所有行,请使用以下命令:5!d 要只显示第五行(也是唯一一行),请使用以下命令:-n '5p'
这两个单行脚本按预期运行。但是,它们会逐行读取整个输入,这对于大型文件来说花费的时间太长。
shell脚本提供了一个“q”(退出)选项来退出进一步的执行。因此,我们可以使用“&&”运算符将这两个命令组合成一行:
命令
$ sed '5!d;q' test.txt
输出
This is line 5, interesting data: Linux is awesome!
命令
$ sed -n '5{p;q}' test.txt
输出
This is line 5, interesting data: Linux is awesome!
我们没有注意到两个输出之间的任何差异,因此让我们使用sed -e's/^.*$//'命令删除从每一行开头到行尾的所有内容。
让我们首先快速浏览一下没有“q”命令的版本。
命令
$ sedsed -d '5!d' test.txt
输出
PATT:This is line 1, I don't have any interesting data.$ HOLD:$ COMM:5 !d PATT:This is line 2, I don't have any interesting data.$ ... This is line 5, interesting data: Linux is awesome! PATT:This is line 6, I don't have any interesting data.$ HOLD:$ COMM:5 !d PATT:This is line 7, I don't have any interesting data.$ HOLD:$ COMM:5 !d
然后我们可以看到sed命令已经从第一个字符处理到最后一个字符(第七个字符)。
我们现在将使用q测试sed命令。
命令
$ sedsed -d '5!d;q' test.txt
输出
PATT:This is line 1, I don't have any interesting data.$ HOLD:$ COMM:5 !d PATT:This is line 2, I don't have any interesting data.$ ... PATT:This is line 5, interesting data: Linux is awesome!$ HOLD:$ COMM:q This is line 5, interesting data: Linux is awesome!
调试输出表明sed处理在第5行停止。
使用awk命令
另一个强大的文本处理工具是awk。您可以使用它用一行代码来解决问题:awk 'NR == 5' input.txt。
我们不想在打印第5行后继续处理。
类似地,awk也有“quit”命令来退出当前处理。
命令
$ awk 'NR==5{ print; exit }' test.txt
输出
This is line 5, interesting data: Linux is awesome!
因此,如输出所示,我们已经解决了这个问题。
使用head和tail命令
我们可以使用`tail`命令提取文本文档的最后部分。
我们还可以使用这两个命令的组合来读取特定行。
让我们假设我们要读取x行。思路是:
我们首先使用head命令从输入文件中获取第1行到第X行。
然后我们将第一步的输出通过管道传递到tail命令以检索最后一个条目:head -n X input | tail -1
让我们看看这个想法对我们的例子是否有效:
命令
$ head -n 5 test.txt | tail -1
输出
I am line 5, interesting data: Linux is awesome!
我们得到了预期的结果,并且我们解决了这个问题。
结论
我们讨论了在Linux中从输入文件读取单行的不同方法。
我们讨论了如何提高bash、awk和/或sed解决方案的性能。
数据结构
网络
关系数据库管理系统(RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP