快速unix命令在文件的中间显示特定的行?

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

使用grep,我find了一个文件的一个区域,我想看看,行347340107。

除了做类似的事情

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

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

更新我完全忘了,grep可以打印一个匹配的上下文…这很好。 谢谢!

用GNU-grep你可以说

  grep --context = 10 ... 

我发现了另外两个解决scheme,如果你知道行号但没有别的(没有grep可能):

假设你需要20到40行,

 sed -n '20,40p;41q' file_name 

要么

 awk 'FNR>=20 && FNR<=40' file_name 
 # print line number 52 sed -n '52p' # method 1 sed '52!d' # method 2 sed '52q;d' # method 3, efficient on large files 

方法3对大文件有效

最快的方式来显示特定的行

不,没有,文件不可行寻址。

在文本文件中没有常量的方法来查找第n行的开始。 您必须通过文件stream水线并计算换行符。

使用最简单/最快的工具来完成这项工作。 对我来说,使用headgrep更有意义,因为后者更复杂。 我并不是说“ grep很慢”,实际上并不是这样,但是如果这种情况比head更快,我会感到惊讶。 基本上,这将是一个错误。

关于什么:

 tail -n +347340107 filename | head -n 100 

我没有testing,但我认为这将工作。

我首先将文件分割成几个较小的文件

 $ split --lines=50000 /path/to/large/file /path/to/output/file/prefix 

然后grep在生成的文件。

我宁愿只是less

  • input5 0 中途转到文件,
  • 43210 G去43210线
  • :43210做同样的事情

和那样的东西。

更好的是:打v来开始编辑(当然是在vim!),在那个位置。 现在请注意, vim具有相同的键绑定!

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

以上命令可以用以下testing文件进行testing:

 seq 1 20 > file.txt 

说明:

  • +-c后跟命令 – 读取文件后执行(vi / vim)命令,
  • -s – 静音模式,也使用当前terminal作为默认输出,
  • q后跟-c是退出编辑器的命令(add !强制退出,例如-scq! )。

sed也需要读取数据来计算行数。 唯一可行的捷径就是文件中的上下文/顺序进行操作。 例如,如果有一些固定宽度的时间/date等前缀的日志行,您可以使用外观 unix实用程序来查找特定date/时间的文件

sed -e '1,N d; M q' sed -e '1,N d; M q'你会打印第N + 1到M行。这可能比grep -C好一点,因为它不会尝试将行匹配到一个模式。

build立在Sklivvz的答案,这是一个很好的function,可以把一个.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 } 

使用

 x=`cat -n <file> | grep <match> | awk '{print $1}'` 

在这里你会得到匹配发生的行号。

现在您可以使用以下命令打印100行

 awk -v var="$x" 'NR>=var && NR<=var+100{print}' <file> 

或者你也可以使用“sed”

 sed -n "${x},${x+100}p" <file> 

<textfile> <line#>显示<textfile><line#> ,只需执行以下操作:

 perl -wne 'print if $. == <line#>' <textfile> 

如果你想要一个更强大的方式来显示正则expression式的范围 – 我不会说为什么grep这样做是一个坏主意,它应该是相当明显的 – 这个简单的expression式会显示你的范围在一个单通这是你处理〜20GB文本文件时所要的:

 perl -wne 'print if m/<regex1>/ .. m/<regex2>/' <filename> 

(小贴士:如果你的正则expression式有/在里面,用m!<regex>!来代替)

这将打印出<filename> ,直到匹配<regex1>的行(包括)与<regex2>匹配的行。

不需要一个巫师就可以看到一些调整可以使它变得更加强大。

最后一件事:因为perl是一种成熟的语言,所以有很多隐藏的增强来支持速度和性能。 考虑到这一点,它最初是为处理大型日志文件,文本,数据库等而开发的,因此它是这种操作的明显select。

你可以试试这个命令:

 egrep -n "*" <filename> | egrep "<line number>" 

容易与Perl! 如果你想从文件中获得第1,3,5行,请说/ etc / passwd:

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