232

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

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

除了做类似的事情

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

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

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

4

18 回答 18

433

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

假设您需要第 20 到 40 行,

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

或者

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

使用sed时,在打印最后一行后退出处理比继续处理直到文件末尾更有效。这在开始时大文件和打印行的情况下尤其重要。为了做到这一点,sed上面的命令引入了指令41q,以便在第 41 行之后停止处理,因为在示例中我们只对第 20-40 行感兴趣。您需要将 41 更改为您感兴趣的最后一行,加一。

于 2008-10-10T14:06:32.503 回答
132
# print line number 52
sed -n '52p' # method 1
sed '52!d' # method 2
sed '52q;d' # method 3,  efficient on large files 

方法 3 对大文件有效

显示特定行的最快方法

于 2013-06-28T14:35:24.587 回答
67

使用 GNU-grep 你可以说

grep --context=10 ...
于 2008-10-10T13:55:48.453 回答
25

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

没有固定时间的方法来查找文本文件中第n行的开头。您必须通过文件流式传输并计算换行符。

使用完成工作所需的最简单/最快的工具。对我来说, using更有意义head,因为后者要复杂得多。我不是说“很慢”,实际上不是,但如果它比这种情况下更快,我会感到惊讶。基本上,那将是一个错误。grepgrepheadhead

于 2008-10-15T13:55:17.187 回答
22

关于什么:

tail -n +347340107 filename | head -n 100

我没有测试它,但我认为这会奏效。

于 2008-10-10T13:58:23.067 回答
16

我更喜欢进入less

  • 键入50%转到文件的一半,
  • 43210G去43210行
  • :43210做同样的事情

和类似的东西。

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

于 2013-08-07T01:16:37.240 回答
14

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

Above commands can be tested with the following test file:

seq 1 20 > file.txt

Explanation:

  • + or -c followed by the command - execute the (vi/vim) command after file has been read,
  • -s - silent mode, also uses current terminal as a default output,
  • q followed by -c is the command to quit editor (add ! to do force quit, e.g. -scq!).
于 2016-07-07T15:51:57.433 回答
12

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

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

然后对生成的文件进行 grep。

于 2008-10-10T15:13:25.003 回答
10

If your line number is 100 to read

head -100 filename | tail -1
于 2018-06-20T05:12:37.560 回答
8

Get ack

Ubuntu/Debian install:

$ sudo apt-get install ack-grep

Then run:

$ ack --lines=$START-$END filename

Example:

$ ack --lines=10-20 filename

From $ 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.
于 2018-03-13T00:05:23.193 回答
4

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

于 2013-08-07T01:01:40.890 回答
4

采用

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>
于 2015-07-30T11:58:08.647 回答
2

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

于 2008-10-10T14:05:10.993 回答
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
}
于 2015-02-03T15:34:55.693 回答
1

要显示 a 中的一行<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,因为它是一门成熟的语言,有许多隐藏的增强功能以​​提高速度和性能。考虑到这一点,它使其成为此类操作的明显选择,因为它最初是为处理大型日志文件、文本、数据库等而开发的。

于 2015-02-07T14:26:58.700 回答
0

你可以试试这个命令:

egrep -n "*" <filename> | egrep "<line number>"
于 2015-10-22T03:26:29.623 回答
0

用 perl 很容易!如果您想从文件中获取第 1、3 和 5 行,例如 /etc/passwd:

perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
于 2016-03-23T13:37:41.983 回答
0

I am surprised only one other answer (by Ramana Reddy) suggested to add line numbers to the output. The following searches for the required line number and colours the output.

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:]]"; }
于 2018-02-09T15:50:53.243 回答