我想模拟GNU的head -n -3
,它打印除了最后3行之外的所有行,因为FreeBSD上的head
没有此功能。所以我想的是像
seq 1 10 | perl -ne ...
这里我使用了10行,但它可以是任何大于3的数字。
可以用Perl或其他方式在BASH的FreeBSD上完成吗?
超级原始解决方案
seq 1 10 | sed '$d' | sed '$d' | sed '$d'
答案 0 :(得分:11)
seq 1 10 | perl -e '@x=("")x3;while(<>){print shift @x;push @x,$_}'
或
perl -e '@x=("")x3;while(<>){print shift @x;push @x,$_}' file
或
command | perl -pe 'BEGIN{@x=("")x3}push @x,$_;$_=shift @x'
perl -pe 'BEGIN{@x=("")x3}push @x,$_;$_=shift @x' file
答案 1 :(得分:9)
seq 1 10 | perl -ne 'push @l, $_; print shift @l if @l > 3'
答案 2 :(得分:7)
纯粹的bash和简单的工具(wc和cut):
head -n $(($(wc -l file | cut -c-8)-3)) file
免责声明 - 我现在无法访问FreeBSD,但这适用于OSX bash。
答案 3 :(得分:6)
这适用于管道和输入文件:
seq 1 10 | perl -e'@x=<>;print@x[0..$#x-3]'
答案 4 :(得分:5)
似乎没有人使用sed
和tac
,所以这里有一个:
$ seq 10 | tac | sed '1,3d' | tac
1
2
3
4
5
6
7
答案 5 :(得分:2)
怎么样:
seq 1 10 | perl -ne 'print if ( !eof )' | perl -ne 'print if ( !eof )' | perl -ne 'print if ( !eof )'
答案 6 :(得分:2)
这个awk单行似乎做了这个工作:
awk '{a[NR%4]=$0}NR>3{print a[(NR-3)%4]}' file
答案 7 :(得分:1)
如果您使用的是4.0或更高版本,请单独使用bash:
seq 1 10 | (readarray -t LINES; printf '%s\n' "${LINES[@]:(-3)}")
更新:这一行将删除最后三行而不是仅显示它们。
seq 1 10 | (readarray -t L; C=${#L[@]}; printf '%s\n' "${L[@]:0:(C > 3 ? C - 3 : 0)}")
为方便起见,它可以放在一个函数上:
function exclude_last_three {
local L C
readarray -t L; C=${#L[@]}
printf '%s\n' "${L[@]:0:(C > 3 ? C - 3 : 0)}"
}
seq 1 10 | exclude_last_three
seq 11 20 | exclude_last_three
答案 8 :(得分:1)
这是一个迟到的答案,因为我昨天遇到了这样的事情。
此解决方案是:
在Ubuntu,Redhat和OSX上测试过。
$ seq 1 10 | { n=3; i=1; while IFS= read -r ln; do [ $i -gt $n ] && cat <<< "${buf[$((i%n))]}"; buf[$((i%n))]="$ln"; ((i++)); done; }
1
2
3
4
5
6
7
$
通过将行读入实现为n元素数组的循环缓冲区来工作。
n是切断文件末尾的行数。
对于我们读取的每一行,我们可以从循环缓冲区回显行i-n,然后将行i存储在循环缓冲区中。在读取前n行之前,不会回显任何内容。 (i mod n)是实现循环缓冲区的数组的索引。
因为要求是单行,所以我试图使其相当简短,不幸的是以牺牲可读性为代价。
答案 9 :(得分:0)
另一种Awk解决方案,它只使用最少量的缓冲区并快速打印线条,而无需先读取所有行。它也可以用于管道和大文件。
awk 'BEGIN{X = 3; for(i = 0; i < X; ++i)getline a[i]}{i %= X; print a[i]; a[i++] = $0}'