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

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

除了做一些

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

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

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


当前回答

简单的perl!如果你想从文件中获得第1、3和5行,输入/etc/passwd:

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

其他回答

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

打印行5

sed -n '5p' file.txt
sed '5q' file.txt

打印第5行以外的所有内容

`sed '5d' file.txt

我用谷歌创建的

#!/bin/bash
#removeline.sh
#remove deleting it comes move line xD

usage() {                                 # Function: Print a help message.
  echo "Usage: $0 -l LINENUMBER -i INPUTFILE [ -o OUTPUTFILE ]"
  echo "line is removed from INPUTFILE"
  echo "line is appended to OUTPUTFILE"
}
exit_abnormal() {                         # Function: Exit with error.
  usage
  exit 1
}

while getopts l:i:o:b flag
do
    case "${flag}" in
        l) line=${OPTARG};;
        i) input=${OPTARG};;
        o) output=${OPTARG};;
    esac
done

if [ -f tmp ]; then
echo "Temp file:tmp exist. delete it yourself :)"
exit
fi

if [ -f "$input" ]; then
   re_isanum='^[0-9]+$'
   if ! [[ $line =~ $re_isanum ]] ; then
      echo "Error: LINENUMBER must be a positive, whole number."
      exit 1
   elif [ $line -eq "0" ]; then
      echo "Error: LINENUMBER must be greater than zero."
      exit_abnormal
   fi
   if [ ! -z $output ]; then
      sed -n "${line}p" $input >> $output
   fi
   if [ ! -z $input ]; then
      # remove this sed command and this comes move line to other file
      sed "${line}d" $input > tmp && cp tmp $input
   fi
fi

if [ -f tmp ]; then
rm tmp
fi

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

得到证实

Ubuntu/Debian 安装:

$ 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.

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

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

然后对结果文件进行grep。