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

问题描述 投票:174回答:18

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

使用grep,我找到了一个我想看一下的文件区域,第347340107行。

做的事情除了

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

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

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

linux bash unix text
18个回答
67
投票

用GNU-grep你可以说

grep --context=10 ...

4
投票

sed还需要读取数据以计算行数。快捷方式可行的唯一方法是在文件中进行上下文/顺序操作。例如,如果前面有固定宽度时间/日期等的日志行,您可以使用look unix实用程序对特定日期/时间的文件进行二进制搜索


3
投票

使用

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>

3
投票

如果你的行号是100来阅读

head -100 filename | tail -1

2
投票

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


2
投票

基于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
}

1
投票

要通过<textfile>显示<line#>中的一行,只需执行以下操作:

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

如果你想要一个更强大的方法来显示一系列带有正则表达式的行 - 我不会说为什么grep这样做是个坏主意,它应该是相当明显的 - 这个简单的表达式将向你显示你的范围处理~20GB文本文件时你想要的单通道:

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

(提示:如果你的正则表达式中有/,请改用m!<regex>!之类的东西)

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

它不需要一个向导来看一些调整如何使它更强大。

最后一件事:perl,因为它是一种成熟的语言,有许多隐藏的增强功能,有利于速度和性能。考虑到这一点,它使它成为这种操作的明显选择,因为它最初是为处理大型日志文件,文本,数据库等而开发的。


0
投票

你可以尝试这个命令:

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

0
投票

perl很容易!如果你想从文件中获取第1,3和5行,请说/ etc / passwd:

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

0
投票

我很惊讶只有另一个答案(由Ramana Reddy提出)建议在输出中添加行号。以下搜索输出所需的行号和颜色。

file=FILE
lineno=LINENO
wb="107"; bf="30;1"; rb="101"; yb="103"
cat -n ${file} | { GREP_COLORS="se=${wb};${bf}:cx=${wb};${bf}:ms=${rb};${bf}:sl=${yb};${bf}" grep --color -C 10 "^[[:space:]]\\+${lineno}[[:space:]]"; }

351
投票

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

假设你需要20到40行,

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

要么

awk 'FNR>=20 && FNR<=40' file_name

101
投票
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

方法3对大文件有效

显示特定线条的最快方式


23
投票

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

在文本文件中没有找到行n开头的常量方法。您必须流式传输文件并计算换行符。

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


19
投票

关于什么:

tail -n +347340107 filename | head -n 100

我没有测试它,但我认为这样可行。


12
投票

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

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

然后grep生成的文件。


11
投票

我更喜欢进入less

  • 键入50%以转到文件的一半,
  • 43210G去43210行
  • :43210也这样做

和那样的东西。

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


8
投票

您可以使用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是退出编辑的命令(添加!强制退出,例如-scq!)。

5
投票

得到确认

ack --lines =开始结束文件名

© www.soinside.com 2019 - 2024. All rights reserved.