通过中间带有“...”的管道打印文件的前几行和后几行
Print first few and last few lines of file through a pipe with "..." in the middle
问题描述
这是我的文件
1
2
3
4
5
6
7
8
9
10
我想通过管道发送这个文件的 cat 输出并接收这个
% cat file | some_command
1
2
...
9
10
尝试过的解决方案
这是我尝试过的一些解决方案及其输出
% cat temp | (head -n2 && echo '...' && tail -n2)
1
2
...
% cat temp | tee >(head -n3) >(tail -n3) >/dev/null
1
2
3
8
9
10
# I don't know how to get the ...
% cat temp | sed -e 1b -e '$!d'
1
10
% cat temp | awk 'NR==1;END{print}'
1
10
# Can only get 2 lines
我建议 bash
:
(head -n 2; echo "..."; tail -n 2) < file
输出:
1
2
...
9
10
您可以考虑这个 awk 解决方案:
awk -v top=2 -v bot=2 'FNR == NR {++n; next} FNR <= top || FNR > n-top; FNR == top+1 {print "..."}' file{,}
1
2
...
9
10
一个awk:
awk -v head=2 -v tail=2 'FNR==NR && FNR<=head
FNR==NR && cnt++==head {print "..."}
NR>FNR && FNR>(cnt-tail)' file file
或者如果单次传递很重要(并且内存允许),您可以使用 perl
:
perl -0777 -lanE 'BEGIN{$head=2; $tail=2;}
END{say join("\n", @F[0..$head-1],("..."),@F[-$tail..-1]);}' file
或者,一个awk就是一个pass:
awk -v head=2 -v tail=2 'FNR<=head
{lines[FNR]=[=12=]}
END{
print "..."
for (i=FNR-tail+1; i<=FNR; i++) print lines[i]
}' file
或者,直接像穴居人一样没有错:
head -2 file; echo "..."; tail -2 file
任何这些印刷品:
1
2
...
9
10
就效率而言,这里有一些统计数据。
对于小文件(即小于 10 MB 左右)所有这些都不到 1 秒,'caveman' 方法是 2 ms.
然后我用 seq 99999999 >file
创建了一个 1.1 GB 的文件
- 两遍awk:50秒
- 一次 perl:10 秒
- 一次通过 awk:29 秒
- 'Caveman': 2 毫秒
两个单通sed
解法:
sed '1,2b
3c\
...
N
$!D'
和
sed '1,2b
3c\
...
$!{h;d;}
H;g'
假设:
- 如 OP 所述,解决方案必须能够处理来自管道的流
- 来自流的总行数未知
- 如果总行数小于
head/tail
偏移量的总和,那么我们将打印重复行(如果 OP 更新问题并提供有关如何解决此问题的更多详细信息,我们可以添加更多逻辑情况)
单程 awk
解决方案,implements a queue in awk 跟踪最近的 N 行;该队列允许我们将 awk's
内存使用限制为仅 N 行(与将整个输入流加载到内存相反,这在可用空间有限的机器上处理大量 lines/data 时可能会出现问题记忆):
h=2 t=3
cat temp | awk -v head=${h} -v tail=${t} '
{ if (NR <= head) print [=10=]
lines[NR % tail] = [=10=]
}
END { print "..."
if (NR < tail) i=0
else i=NR
do { i=(i+1)%tail
print lines[i]
} while (i != (NR % tail) )
}'
这会生成:
1
2
...
8
9
10
演示重叠问题:
$ cat temp4
1
2
3
4
使用 h=3;t=3
建议的 awk
代码生成:
$ cat temp4 | awk -v head=${h} -v tail=${t} '...'
1
2
3
...
2
3
4
这是否是 'correct' 输出将取决于 OP 的要求。
问题描述
这是我的文件
1
2
3
4
5
6
7
8
9
10
我想通过管道发送这个文件的 cat 输出并接收这个
% cat file | some_command
1
2
...
9
10
尝试过的解决方案
这是我尝试过的一些解决方案及其输出
% cat temp | (head -n2 && echo '...' && tail -n2)
1
2
...
% cat temp | tee >(head -n3) >(tail -n3) >/dev/null
1
2
3
8
9
10
# I don't know how to get the ...
% cat temp | sed -e 1b -e '$!d'
1
10
% cat temp | awk 'NR==1;END{print}'
1
10
# Can only get 2 lines
我建议 bash
:
(head -n 2; echo "..."; tail -n 2) < file
输出:
1 2 ... 9 10
您可以考虑这个 awk 解决方案:
awk -v top=2 -v bot=2 'FNR == NR {++n; next} FNR <= top || FNR > n-top; FNR == top+1 {print "..."}' file{,}
1
2
...
9
10
一个awk:
awk -v head=2 -v tail=2 'FNR==NR && FNR<=head
FNR==NR && cnt++==head {print "..."}
NR>FNR && FNR>(cnt-tail)' file file
或者如果单次传递很重要(并且内存允许),您可以使用 perl
:
perl -0777 -lanE 'BEGIN{$head=2; $tail=2;}
END{say join("\n", @F[0..$head-1],("..."),@F[-$tail..-1]);}' file
或者,一个awk就是一个pass:
awk -v head=2 -v tail=2 'FNR<=head
{lines[FNR]=[=12=]}
END{
print "..."
for (i=FNR-tail+1; i<=FNR; i++) print lines[i]
}' file
或者,直接像穴居人一样没有错:
head -2 file; echo "..."; tail -2 file
任何这些印刷品:
1
2
...
9
10
就效率而言,这里有一些统计数据。
对于小文件(即小于 10 MB 左右)所有这些都不到 1 秒,'caveman' 方法是 2 ms.
然后我用 seq 99999999 >file
- 两遍awk:50秒
- 一次 perl:10 秒
- 一次通过 awk:29 秒
- 'Caveman': 2 毫秒
两个单通sed
解法:
sed '1,2b
3c\
...
N
$!D'
和
sed '1,2b
3c\
...
$!{h;d;}
H;g'
假设:
- 如 OP 所述,解决方案必须能够处理来自管道的流
- 来自流的总行数未知
- 如果总行数小于
head/tail
偏移量的总和,那么我们将打印重复行(如果 OP 更新问题并提供有关如何解决此问题的更多详细信息,我们可以添加更多逻辑情况)
单程 awk
解决方案,implements a queue in awk 跟踪最近的 N 行;该队列允许我们将 awk's
内存使用限制为仅 N 行(与将整个输入流加载到内存相反,这在可用空间有限的机器上处理大量 lines/data 时可能会出现问题记忆):
h=2 t=3
cat temp | awk -v head=${h} -v tail=${t} '
{ if (NR <= head) print [=10=]
lines[NR % tail] = [=10=]
}
END { print "..."
if (NR < tail) i=0
else i=NR
do { i=(i+1)%tail
print lines[i]
} while (i != (NR % tail) )
}'
这会生成:
1
2
...
8
9
10
演示重叠问题:
$ cat temp4
1
2
3
4
使用 h=3;t=3
建议的 awk
代码生成:
$ cat temp4 | awk -v head=${h} -v tail=${t} '...'
1
2
3
...
2
3
4
这是否是 'correct' 输出将取决于 OP 的要求。