试图调试服务器的一个问题,我唯一的日志文件是一个20GB的日志文件(甚至没有时间戳!)为什么人们使用System.out.println()作为日志?在生产吗? !)
使用grep,我找到了我想要查看的文件区域,第347340107行。
除了做一些
head -<$LINENUM + 10> filename | tail -20
... 这将需要头读取日志文件的前3.47亿行,是否有一个快速而简单的命令将行347340100 - 347340200(例如)转储到控制台?
我完全忘记了grep可以打印匹配前后的上下文…这很有效。谢谢!
我发现了其他两个解决方案,如果你知道行号,但没有其他(没有grep可能):
假设你需要第20到40行,
sed -n '20,40p;41q' file_name
or
awk 'FNR>=20 && FNR<=40' file_name
When using sed it is more efficient to quit processing after having printed the last line than continue processing until the end of the file. This is especially important in the case of large files and printing lines at the beginning. In order to do so, the sed command above introduces the instruction 41q in order to stop processing after line 41 because in the example we are interested in lines 20-40 only. You will need to change the 41 to whatever the last line you are interested in is, plus one.
要通过<line#>显示<textfile>中的一行,只需这样做:
perl -wne 'print if $. == <line#>' <textfile>
如果你想用更强大的方法用正则表达式来显示一行范围——我不会说为什么grep是一个坏主意,这应该是相当明显的——这个简单的表达式将在一次传递中显示你的范围,这是你在处理~20GB文本文件时想要的:
perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename>
(提示:如果你的regex中有/,使用类似m!<regex>!相反)
这将打印出<filename>,从匹配<regex1>的行开始,直到(并包括)匹配<regex2>的行。
不需要一个向导,就可以看到一些调整可以使它更加强大。
最后一点:perl,因为它是一种成熟的语言,有许多隐藏的增强来提高速度和性能。考虑到这一点,它成为这种操作的明显选择,因为它最初是为处理大型日志文件、文本、数据库等而开发的。
你可以使用ex命令,一个标准的Unix编辑器(现在是Vim的一部分),例如。
显示单行(例如第二行):
Ex +2p -scq file.txt
对应的sed语法:sed -n '2p' file.txt
行范围(例如2-5行):
Ex +2,5p -scq file.txt
Sed语法:Sed -n '2,5p' file.txt
从给定的行到末尾(例如,第5行到文件末尾):
Ex +5,p -scq file.txt
Sed语法:Sed -n '2,$p' file.txt
多行范围(例如2-4行和6-8行):
Ex +2,4p +6,8p -scq file.txt
Sed语法:Sed -n '2,4p;6,8p' file.txt
以上命令可以用下面的测试文件进行测试:
seq 1 20 > file.txt
解释:
+或-c后跟命令-读取文件后执行(vi/vim)命令,
-s -静默模式,也使用当前终端作为默认输出,
Q后面加-c是退出编辑器的命令(add !强制退出,例如-scq!)。
得到证实
Ubuntu/Debian 安装:
$ sudo apt-get install ack-grep
然后运行:
$ ack --lines=$START-$END filename
例子:
$ ack --lines=10-20 filename
来自$ man ack:
--lines=NUM
Only print line NUM of each file. Multiple lines can be given with multiple --lines options or as a comma separated list (--lines=3,5,7). --lines=4-7 also works.
The lines are always output in ascending order, no matter the order given on the command line.