截断管道文本的中间并在一个命令中替换为省略号
Truncate middle of piped text and replace with ellipsis in one command
我有一个很长的文本流,开始发送到 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。那可能吗?怎么样?
这是一个 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;
}
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 的建议。比我的解决方案更节省内存:
seq 5010 | awk '
NR <= 5
{l5=l4; l4=l3; l3=l2; l2=l1; l1=[=13=]}
END {print "..."; print l5; print l4; print l3; print l2; print l1}
'
我有一个很长的文本流,开始发送到 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。那可能吗?怎么样?
这是一个 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;
}
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 的建议。比我的解决方案更节省内存:
seq 5010 | awk '
NR <= 5
{l5=l4; l4=l3; l3=l2; l2=l1; l1=[=13=]}
END {print "..."; print l5; print l4; print l3; print l2; print l1}
'