题 如何在Linux中显示文本文件中的某些行?


我想每个人都知道有用的Linux cmd行实用程序 head 和 tailhead 允许您打印文件的前X行, tail 做同样但打印文件的结尾。打印文件中间的好命令是什么?就像是 middle --start 10000000 --count 20 (打印10'000'000到10'000'010行)。

我正在寻找能够有效处理大文件的东西。我试过了 tail -n 10000000 | head 10 它的速度非常慢。


73
2018-04-19 08:53




可能重复 serverfault.com/questions/101900/... - Kyle Brandt♦


答案:


sed -n '10000000,10000020p' filename

你可能能够加快这一点:

sed -n '10000000,10000020p; 10000021q' filename

在这些命令中,选项 -n 原因 sed “抑制图案空间的自动打印”。该 p 命令“打印[s]当前模式空间”和 q 命令“立即退出[s] sed脚本而不再处理任何输入......”引号来自 sed  man 页

顺便说一句,你的命令

tail -n 10000000 filename | head 10

从第一百万行开始 结束 这个文件,而你的“中间”命令似乎从第一百万分之一开始 开始 这相当于:

head -n 10000010 filename | tail 10

问题是对于具有可变长度行的未排序文件,任何进程都必须通过计算换行的文件。没有办法快捷。

但是,如果文件已排序(例如,带有时间戳的日志文件)或具有固定长度的行,则可以根据字节位置搜索文件。在日志文件示例中,您可以作为我的Python脚本进行一段时间的二进制搜索 这里*没有。在固定记录长度文件的情况下,它真的很容易。你只是寻求 linelength * linecount 字符进入文件。

*我有意义发布该脚本的另一个更新。也许我会在这些日子里解决这个问题。


93
2018-04-19 09:11



这里有一个 sed 查尔斯的版本 middle 功能: middle() { local s=$1 c=$2; shift 2; sed -n "$s,$(($s + $c -1))p; $(($s + $c))q" "$@"; }。它将处理多个文件参数,带有空格的文件名等。多个文件一起处理,就像它们被以同样的方式被捕获一样 sed 通常会这样做(因此,如果第一个文件的行数少于1100行,则中间1000 100 file1 file2将跨越第一个文件的末尾到第二个文件的开头)。 - Dennis Williamson
可以使用filename参数调用我之前注释中的函数: middle startline count filename 或多个文件名: middle startline count file1 file2 file3 或者使用重定向: middle startline count < filename 或在管道中: some_command | 中间起始线计数`或 cat file* | middle startline count - Dennis Williamson
你的sed命令中的`不应该是'?我不能让它与反引号一起工作,但它与单引号一起正常工作。 - Ian Hunter
@beanland:是的,这是一个错字。我修好了。谢谢。 - Dennis Williamson
@kev:我在答案中加了一些解释。 - Dennis Williamson


我发现了以下用法 sed

sed -n '10000000,+20p'  filename

希望它对某人有用!


25
2018-06-17 18:22



很高兴知道Dennis提出的最后一行参数有一个替代方案:行数为秒 sed -n 使其具有可读性的参数。 - user3123159
示例用法: extract_lines(){sed -n "$1,+$2p" <file>} 写入stdout。 - user3123159


这是我第一次在这里发帖!无论如何,这个很容易。假设您要从名为file.txt的文件中提取第8872行。这是你如何做到的:

cat -n file.txt | grep'^ * 8872'

现在的问题是在此之后找到20行。要做到这一点,你做到了

cat -n file.txt | grep -A 20'^ * 8872'

对于周围或之前的行,请参阅grep手册中的-B和-C标志。


4
2018-05-23 12:11



虽然这在技术上是正确的并且是在一个合理大小的文件上进行的有趣方式,但我很好奇它在处理海报所要求的大小的文件时的功效。 - Jenny D
多行:cat -n file.txt | grep“^ \ s \ +(10 \ | 20 \ | 30)\ s \ +” - Jeff K.
cat -n file.txt | grep '^ *1' 产生右侧有1个的所有线。如何用这种技术输出第1行?我知道我可以领先-n 1 ....但是如何使用grep? - Sean87


丹尼斯的回答是要走的路。但是在bash下只使用head&tail:

middle(){head -n $ [$ 1 + $ 2] |尾巴-n $ 2; }

这会扫描前两行$ 1 + $ 2,所以比Dennis的回答要糟糕得多。但你不需要记住所有那些sed字母使用它....


1
2018-04-19 15:08



运用 $[...] 已弃用,至少在Bash中。此外,您缺少文件参数。 - Dennis Williamson
@Dennis:没有遗漏参数:你打算在stdin上使用它,按照 middle 10 10 < /var/log/auth.log。 - Charles Stewart


使用以下命令获取特定范围的行

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

这里debug.log是我的文件,它由缺少的行组成,我用来打印从1220974行号到1513793的行到文件test.log。 希望它有助于捕捉线条范围。


1
2018-04-17 19:48



答案一样 serverfault.com/a/641252/140016。 Downvoted。 - Deer Hunter
答案不一样。这对于大文件应该更快,因为它在打印最后一行后实际中止,而不是继续扫描文件。 - phobic


红宝石oneliner版本。

ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

它对某些人有用。 Dennis和Dox提供的'sed'解决方案非常好,即使它看起来更快。


0
2018-05-23 12:58





你可以使用'nl'。

nl filename | grep <line_num>

0
2017-10-31 19:35





例如,这个awk将打印20到40之间的行

awk'{if((NR> 20)&&(NR <40))print $ 0}'/ etc / passwd


0
2017-10-31 22:02





如果您知道行的数字,假设您想从文件中获取第1,3和5行,请说/ etc / passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd

0
2018-03-23 13:36