我想每个人都知道有用的Linux cmd行实用程序headtailhead允许您打印文件的前X行,tail可以执行相同的操作,但是打印文件的末尾。什么是打印文件中间的好命令?类似于middle --start 10000000 --count 20(打印第10'000'000至第10'000'010行)。

我正在寻找可以有效处理大型文件的东西。我尝试过tail -n 10000000 | head 10,速度非常慢。

评论

serverfault.com/questions/101900 / ...的可能重复项...

#1 楼

sed -n '10000000,10000020p' filename


您也许可以像这样加快速度:

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


在这些命令中,选项-n导致sed变为“禁止自动打印图案空间”。 p命令“打印当前模式空间”和q命令“立即退出sed脚本而不处理更多输入...”引号来自sed man页面。

顺便说一句,您的命令

tail -n 10000000 filename | head 10


从文件末尾的第1百万行开始,而您的“中间”命令似乎从从开始算起的十分之一等于:

head -n 10000010 filename | tail 10


问题是对于具有可变长度行的未排序文件,任何处理都将必须遍历该文件计算换行符。没有捷径可以实现。

但是,如果文件已排序(例如,带有时间戳的日志文件)或具有固定长度的行,则可以基于字节查找文件位置。在日志文件示例中,您可以像我的Python脚本*那样在一定范围内进行二进制搜索。对于固定记录长度的文件,这确实很容易。您只需要在文件中查找linelength * linecount个字符即可。

*我的意思是发布该脚本的另一个更新。也许我会在这几天中解决它。

评论


这是Charles中间函数的sed版本:middle(){local s = $ 1 c = $ 2; 2班; sed -n“ $ s,$((($ s + $ c -1))p; $(($ s + $ c))q”“ $ @”; }。它将处理多个文件参数,带空格的文件名等。多个文件将像sed正常处理一样被处理在一起(因此,中间的1000 100 file1 file2将跨越第一个文件的末尾到如果第一个少于1100行,则从第二个开始。

–丹尼斯·威廉姆森
2010-4-19的15:55

我上一条注释中的函数可以使用文件名参数调用:中间起始行计数文件名或多个文件名:中间起始行计数文件1 file2 file3或重定向:中间起始行计数<文件名或在管道中:some_command |中间起始行计数`或cat文件* |起始行中间计数

–丹尼斯·威廉姆森
10-4-20在16:47

sed命令中的`不应为'吗?我无法将其与反引号一起使用,但单引号可以正常使用。

–伊恩·亨特(Ian Hunter)
2012-12-18 21:51

@beanland:是的,这是一个错字。我已经解决了。谢谢。

–丹尼斯·威廉姆森
2012年12月19日下午5:57

@kev:我在回答中添加了一些解释。

–丹尼斯·威廉姆森
17-10-10在16:19

#2 楼

我发现sed的以下用法

sed -n '10000000,+20p'  filename


希望对某人有用!

评论


很高兴知道,Dennis提出的最后一个参数行有一个替代:行数作为第二个sed -n参数,使它相当易读。

– Timo
18-2-3在9:46



用法示例:extract_lines(){sed -n“ $ 1,+ $ 2p” }写入标准输出。

– Timo
18年2月3日,9:50



#3 楼

这是我第一次在这里发布!无论如何,这很容易。假设您要从名为file.txt的文件中提取第8872行。这是您的操作方法:

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

现在的问题是在这之后找到20行。为此,您可以执行

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

有关周围或之前的内容,请参见grep手册中的-B和-C标志。

评论


尽管从技术上讲这是正确的,并且是在合理大小的文件上执行此操作的有趣方法,但我对它在处理海报要求的大小的文件时的有效性感到好奇。

–珍妮D
2014年5月23日12:37

多行:cat -n file.txt | grep“ ^ \ s \ +(10 \ | 20 \ | 30)\ s \ +”

–杰弗里·奈特(Jeffrey Knight)
16年11月11日15:24



cat -n file.txt | grep'^ * 1'产生所有右边有1的行。如何用这种技术输出第1行?我知道我可以-n 1 ....但是如何使用grep?

– Sean87
17年5月26日在10:59

#4 楼

丹尼斯的sed答案是正确的方法。但是在bash下只使用头部和尾部:

middle () { head -n $[  +  ] | tail -n ; }


这会扫描前$ 1 + $ 2行两次,因此比Dennis的答案差很多。但是您无需记住所有这些sed字母即可使用它。...

评论


至少在Bash中不建议使用$ [...]。另外,您缺少文件参数。

–丹尼斯·威廉姆森
2010-4-19的15:46

@Dennis:不丢失参数:您应该在stdin上使用它,按照中间10 10
–查尔斯·斯图尔特
10-4-20在16:33

#5 楼

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

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


这是debug.log,这是我的文件,其中缺少行,并且我习惯于从中打印行1220974行号到1513793到文件test.log。
希望它对捕获行范围很有帮助。

评论


答案与serverfault.com/a/641252/140016相同。不赞成投票。

–鹿猎人
15年4月17日在20:32

答案不一样。对于大型文件,这应该更快一些,因为它实际上在打印最后一行后中止,而不是继续扫描文件。

–恐惧
18年7月6日在8:53

#6 楼

红宝石oneliner版本。

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


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

#7 楼

您可以使用'nl'。

nl filename | grep <line_num>


评论


这不好:如果您请求第42行,您将获得包含该数字的所有行。

–塞缪尔·福尔(Samuel Faure)
20年1月4日,11:12

#8 楼

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


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


#9 楼

如果知道行号,则说要从文件中获取行1、3和5,请说/ etc / passwd:

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


#10 楼

Perl为王:

perl -ne 'print if ($. == 10000000 .. $. == 10000020)' filename