代码之家  ›  专栏  ›  技术社区  ›  matt b

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

  •  164
  • matt b  · 技术社区  · 17 年前

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

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

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

    使现代化

    18 回复  |  直到 10 年前
        1
  •  426
  •   Sklivvz    4 年前

    我找到另外两个 solutions

    假设您需要第20到40行,

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

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

    使用时 sed 塞德 上面的命令介绍了指令 41q 为了在第41行之后停止处理,因为在本例中,我们只对第20-40行感兴趣。您需要将41改为您感兴趣的最后一行,再加上一行。

        2
  •  130
  •   WCC    13 年前
    # print line number 52
    sed -n '52p' # method 1
    sed '52!d' # method 2
    sed '52q;d' # method 3,  efficient on large files 
    

    方法3对大文件有效

        3
  •  67
  •   Mathias Weidner Mathias Weidner    17 年前

    grep --context=10 ...
        4
  •  25
  •   unwind    11 年前

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

    没有固定时间的方法可以找到行的起点 在文本文件中。您必须对文件进行流式处理并计算换行数。

    使用最简单/最快的工具来完成这项工作。对我来说,使用 head 制造 更有意义 grep 格雷普 它真的不慢,但如果它的速度比 大体上

        5
  •  21
  •   JJD    12 年前

    tail -n +347340107 filename | head -n 100
    

    我没有测试它,但我认为它会起作用。

        6
  •  14
  •   sehe    12 年前

    我更喜欢直接进入大学 less

    • 打字 0 要转到文件的一半,
    • 43210 G
    • :43210

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

        7
  •  12
  •   JJD    12 年前

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

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

        8
  •  12
  •   kenorb    10 年前

    ex

    • 显示一行(例如第二行):

      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 -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 然后 ! 强制退出,例如。 -scq! ).
        9
  •  9
  •   wscourge Kiran Balakrishnan    8 年前

    head -100 filename | tail -1
    
        10
  •  8
  •   Eyal Levin    6 年前

    收到 ack

    $ 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.
    
        11
  •  4
  •   pixelbeat    12 年前

    唯一可能的快捷方式是在文件中有上下文/顺序进行操作。例如,如果日志行前面有固定宽度的时间/日期等。 你可以使用

        12
  •  4
  •   Ramana Reddy    10 年前

    使用

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

    在这里,您将获得匹配发生的行号。

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

    或者也可以使用“sed”

    sed -n "${x},${x+100}p" <file>
    
        13
  •  2
  •   mweerden    17 年前

    具有 sed -e '1,N d; M q' 您将打印N+1到M行。这可能会更好一些 grep -C

        14
  •  2
  •   Keithel    11 年前

    基于Sklivz的回答,我们可以在 .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
    }
    
        15
  •  1
  •   Sklivvz    11 年前

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

        16
  •  0
  •   bish    10 年前

    egrep -n "*" <filename> | egrep "<line number>"
    
        17
  •  0
  •   dagelf    8 年前

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

    perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
    
        18
  •  0
  •   eel ghEEz    8 年前

    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:]]"; }
    
    推荐文章