试图调试服务器的一个问题,我唯一的日志文件是一个20GB的日志文件(甚至没有时间戳!)为什么人们使用System.out.println()作为日志?在生产吗? !)

使用grep,我找到了我想要查看的文件区域,第347340107行。

除了做一些

head -<$LINENUM + 10> filename | tail -20 

... 这将需要头读取日志文件的前3.47亿行,是否有一个快速而简单的命令将行347340100 - 347340200(例如)转储到控制台?

我完全忘记了grep可以打印匹配前后的上下文…这很有效。谢谢!


当前回答

你可以使用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!)。

其他回答

我发现了其他两个解决方案,如果你知道行号,但没有其他(没有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.

基于Sklivvz的回答,这里有一个可以放入.bash_aliases文件中的很好的函数。当从文件的前面打印东西时,它对巨大的文件是有效的。

function middle()
{
    startidx=$1
    len=$2
    endidx=$(($startidx+$len))
    filename=$3

    awk "FNR>=${startidx} && FNR<=${endidx} { print NR\" \"\$0 }; FNR>${endidx} { print \"END HERE\"; exit }" $filename
}

是什么:

tail -n +347340107 filename | head -n 100

我没有测试,但我认为这是可行的。

Sed还需要读取数据来计算行数。 唯一可能的快捷方式是文件中有上下文/顺序可以操作。例如,如果日志行前面有固定宽度的时间/日期等。 您可以使用look Unix实用程序在文件中查找特定的日期/时间

你可以说GNU-grep

grep --context=10 ...