目标是缩短大文本:
删除前X行和最后Y行之间的所有内容
并且可能在中间插入一条如“截断到XY线的文件......”之类的线
我玩了很多次,用奇怪的重定向(Pipe output to two different commands),子壳,
tee
和多次sed
次调用,我想知道是否
sed -e '10q'
和
sed -e :a -e '$q;N;11,$D;ba'
通过将两者合并为单个sed调用,可以简化。
提前致谢
答案 0 :(得分:2)
使用 head 和 tail :
(head -$X infile; echo Truncated; tail -$Y infile) > outfile
或 awk :
awk -v x=$x -v y=$y '{a[++i]=$0}END{for(j=1;j<=x;j++)print a[j];print "Truncated"; for(j=i-y;j<=i;j++)print a[j]}' yourfile
或者如果正如您所说,输入来自管道,您可以使用 tee 进行流程替换:
yourcommand | tee >(head -$x > p1) | tail -$y > p2 ; cat p[12]
答案 1 :(得分:1)
你可以通过魔术咒语,流程替换和stdio重定向来实现:
x=5 y=8
seq 20 | {
tee >(tail -n $y >&2) \
>({ head -n $x; echo "..."; } >&2) >/dev/null
} 2>&1
1
2
3
4
5
...
13
14
15
16
17
18
19
20
此版本更顺序,输出应保持一致:
x=5 y=8
seq 20 | {
{
# read and print the first X lines to stderr
while ((x-- > 0)); do
IFS= read -r line
echo "$line"
done >&2
echo "..." >&2
# send the rest of the stream on stdout
cat -
} |
# print the last Y lines to stderr, other lines will be discarded
tail -n $y >&2
} 2>&1
答案 2 :(得分:0)
这是一个不需要知道文件长度的sed替代方案。
您可以将修改后的“head”表达式插入到“tail”表达式的滑动循环中。 E.g:
sed ':a; 10s/$/\n...File truncated.../p; $q; N; 11,$D; ba'
请注意,如果范围重叠,则输出中将出现重复的行。
示例:
seq 30 | sed ':a; 10s/$/\n...File truncated.../p; $q; N; 11,$D; ba'
输出:
1
2
3
4
5
6
7
8
9
10
...File truncated...
20
21
22
23
24
25
26
27
28
29
30
这是一个注释的多行版本,用于解释正在发生的事情:
:a # loop label
10s/$/\n...File truncated.../p # on line 10, replace end of pattern space
$q # quit here when on the last line
N # read next line into pattern space
11,$D # from line 11 to end, delete the first line of pattern space
ba # goto :a
答案 3 :(得分:0)
如果您知道文件的长度
EndStart=$(( ${FileLen} - ${Y} + 1))
sed -n "1,${X} p
${X} a\\
--- Truncated part ---
${EndStart},$ p" YourFile
答案 4 :(得分:0)
这可能适合你(GNU sed):
sed '1,5b;:a;N;s/\n/&/8;Ta;$!D;s/[^\n]*\n//;i\*** truncated file ***' file
此处x=5
和Y=8
。
N.B。这样可以保留简短的文件。
答案 5 :(得分:0)
您还可以使用sed -u 5q
(使用GNU sed
)作为head -n5
的无缓冲替代方案:
$ seq 99|(sed -u 5q;echo ...;tail -n5)
1
2
3
4
5
...
95
96
97
98
99