截断管道文本的中间部分,并在一个命令中用省略号替换

时间:2015-01-26 21:00:41

标签: bash shell

我有一个非常长的文本流,它开始发送到stdout。在bash中,我可以通过运行显示前几行:

$ seq 1 5010 | head 5
1
2
3
4
5

或结束

$ seq 1 5010 | tail 5
5006
5007
5008
5009
5010

但是我需要显示前5个和后5个以及中间的省略号...所以输出可能看起来像

1
2
3
4
5
...
5006
5007
5008
5009
5010

我需要在一个单行的库存bash中这样做。那可能吗?怎么样?

2 个答案:

答案 0 :(得分:4)

这是一个bash(v4)解决方案:

seq 1 5010 | { mapfile -tn 5 a; printf "%s\n" "${a[@]}" ...; tail -n 5; }

在v3上,以下内容应该有效(尽管这是一个更长的行):

seq 1 5010 | {
  for x in 1 2 3 4 5; do IFS= read -r; echo "$REPLY"; done;
  echo ...;
  tail -n 5;
}

答案 1 :(得分:2)

的Perl:

seq 5010 | perl -0nE '@lines = split /\n/; say join "\n", @lines[0..4], "...", @lines[-5..-1]'
1
2
3
4
5
...
5006
5007
5008
5009
5010

等效awk:

awk -v RS="" '{
    for (i=1; i<=5; i++) print $i
    print "..."
    for (i=NF-4; i<=NF; i++) print i
}'

这是Etan的建议。比我的solutinos更节省内存的方式:

seq 5010 | awk '
    NR <= 5 
    {l5=l4; l4=l3; l3=l2; l2=l1; l1=$0} 
    END {print "..."; print l5; print l4; print l3; print l2; print l1}
'