head
和tail
。 head
允许您打印文件的前X行,tail
可以执行相同的操作,但是打印文件的末尾。什么是打印文件中间的好命令?类似于middle --start 10000000 --count 20
(打印第10'000'000至第10'000'010行)。我正在寻找可以有效处理大型文件的东西。我尝试过
tail -n 10000000 | head 10
,速度非常慢。#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
评论
serverfault.com/questions/101900 / ...的可能重复项...