首页 > 解决方案 > 使用 Bash 将文本文件的最后 n 行移动到顶部

问题描述

如何在不知道文件行数的情况下将文本文件的最后 n 行移到顶部?sed是否可以使用单个命令行(例如)来实现这一点?

从:

...
a
b
c
d

至:

a
b
c
d
...

标签: bashsedcommand

解决方案


2021 年更新:

使用 vim 的 ex 模式更简单:(受此答案启发)

vim - -esc '$-3,$m0|%p|q!' --not-a-term         # when processing a pipe
vim file.txt -esc '$-3,$m0|%p|q!' --not-a-term  # when processing a file
vim file.txt -esc '$-3,$m0|wq' --not-a-term     # when editing a file inline

这会将最后 4 行(最后一行 + 最后一行之前的 3 行)移到顶部。更改3为您想要的号码。

一个 MWE:

seq 10 | vim - '-esc$-3,$m0|%p|q!' --not-a-term

输出:

7
8
9
10
1
2
3
4
5
6

2020 年更新:

如果输入源来自管道,您可能会发现很难。在这种情况下,您可以使用

awk '{a[NR-1]=$0}END{for(i=0;i<NR;++i)print(a[(i-4+NR)%NR])}'

这会将所有行存储在内存中(这可能是一个问题),然后输出它们。更改4命令以查看不同的结果。


显示最后 n 行,然后显示其余的:

tail -n 4 file; head -n -4 file

来自man head

-n, --lines=[-]NUM

打印前 NUM 行而不是前 10 行;使用前导“-”,打印每个文件的最后 NUM 行以外的所有行

tail -n 4将显示文件的最后 4 行。

如果您希望通过管道传输这些数据,您需要像这样将它们放在一起:

( tail -n 4 file; head -n -4 file ) | wc

或者,也许您可​​以使用 vim 内联编辑文件:

vim +'$-3,$m0' +'wq' file

vim的+选项将运行它后面的 (Ex) 命令。$-3,$m0表示将最后一行上方的 3 行之间的行和最后一行移到文件的开头。+请注意,和命令之间不应有空格。


或者在 vim 正常模式下使用命令:

vim +'norm G3kdGggPZZ' file

G转到文件末尾;3k上移 3 行;dG删除到文件末尾;gg转到文件顶部;P在此行之前粘贴已删除的行;ZZ保存并退出。


推荐阅读