如何反转文件中的行顺序?

Sco*_*len 591 unix shell command-line

我想颠倒文本文件(或stdin)中行的顺序,保留每行的内容.

所以,即从以下开始:

foo
bar
baz
Run Code Online (Sandbox Code Playgroud)

我想结束

baz
bar
foo
Run Code Online (Sandbox Code Playgroud)

是否有标准的UNIX命令行实用程序?

Mih*_*șan 1311

另外值得一提:( tac咳嗽,反向cat).部分的coreutils.

将一个文件翻转到另一个文件中

tac a.txt > b.txt
Run Code Online (Sandbox Code Playgroud)

  • 特别值得一提的是使用没有-r选项的尾部版本!(大多数Linux人都有GNU尾部,没有-r,所以我们有GNU tac). (66认同)
  • 如果你将OS X与自制软件一起使用,你可以使用`brew install coreutils`安装tac(默认情况下安装为`gtac`). (24认同)
  • 只是一个注释,因为人们之前已经提到了tac,但是Tac似乎没有安装在OS X上.并不是说在Perl中编写替代品并不困难,但我没有真正的替代品. (10认同)
  • 问题之一是,如果文件没有尾随新行,前 2 行可能会合并为 1 行。`echo -n "abc\ndee" > 测试;tac 测试`。 (6认同)
  • 你可以从Fink获得OS X的GNU tac.您可能希望获得GNU尾部,因为它做了一些BSD尾部没有的东西. (5认同)
  • 重要的是,您还可以通过管道输入 tac:`cat a.txt | tac >b.txt` 有效! (2认同)

Jas*_*hen 423

BSD尾巴:

tail -r myfile.txt
Run Code Online (Sandbox Code Playgroud)

参考:FreeBSD,NetBSD,OpenBSDOS X手册页.

  • 使用Unix命令"tac"(与cat相反) (313认同)
  • 请记住'-r'选项不符合POSIX标准.下面的sed和awk解决方案甚至可以在最恶劣的系统中运行. (111认同)
  • 刚在Ubuntu 12.04上试过这个,发现我的尾巴版本没有-r选项(8.13).请改用"tac"(参见Mihai的答案). (25认同)
  • 复选标记应在下方移至tac.尾部-r在Ubuntu 12/13,Fedora 20,Suse 11上失败. (7认同)
  • tail -r ~/1 ~ tail: invalid option -- r 尝试使用 `tail --help' 获取更多信息。看起来像它的新选项 (3认同)
  • 答案当然应该提到这只是BSD,特别是因为OP要求"标准UNIX"实用程序.这不是GNU尾部所以它甚至不是事实上的标准. (2认同)
  • 虽然对某些人有用,但这并不能解决所提出的问题.即它不是"标准UNIX命令行实用程序". (2认同)

eph*_*ent 153

有着名的sed技巧:

# reverse order of lines (emulates "tac")
# bug/feature in HHsed v1.5 causes blank lines to be deleted
sed '1!G;h;$!d'               # method 1
sed -n '1!G;h;$p'             # method 2
Run Code Online (Sandbox Code Playgroud)

(说明:在非初始行前加上保持缓冲区,交换行和保持缓冲区,在末尾打印出行)

或者(更快的执行)来自awk单行:

awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*
Run Code Online (Sandbox Code Playgroud)

如果你不记得了,

perl -e 'print reverse <>'
Run Code Online (Sandbox Code Playgroud)

在具有GNU实用程序的系统上,其他答案更简单,但并非全世界都是GNU/Linux ...

  • 我希望这个是接受的答案.coz sed总是可用的,但不是`tail -r`和tac. (8认同)
  • 来自同一个来源:awk'{a [i ++] = $ 0} END {for(j = i-1; j> = 0;)打印一个[j--]}'文件*sed和awk版本都可以工作我的busybox路由器.'tac'和'tail -r'没有. (4认同)

Der*_*ike 59

如果你正好在vim使用中

:g/^/m0
Run Code Online (Sandbox Code Playgroud)

  • 相关:[如何颠倒行的顺序?](http://vi.stackexchange.com/q/2105/467)在Vim SE (5认同)
  • g表示"全局执行此操作.^表示"行的开头".m表示"将行移动到新行号.0是要移动到哪一行.0表示"在当前行1之前的文件顶部".所以:"查找具有开头的每一行,并将其移至第0行." 您找到第1行,并将其移至顶部.什么也没做.然后找到第2行并将其移到第1行上方,到达文件顶部.现在找到第3行并将***移到顶部.每行重复此操作.最后,您将最后一行移至顶部.当你完成后,你已经扭转了所有的路线. (5认同)
  • 如果您简短地解释了它的工作,我会投票赞成。 (3认同)
  • 是的,我得到了那个,但我的意思是分解vim命令的各个部分正在做什么.我现在看看@kenorb链接的答案,它提供了解释. (2认同)

Dig*_*oss 42

$ (tac 2> /dev/null || tail -r)
Run Code Online (Sandbox Code Playgroud)

试试tac,适用于Linux,如果不起作用tail -r,可以在BSD和OSX上运行.

  • @sage,如果`tac`不可用,则回退到`tail -r`.`tac`不符合POSIX标准.也不是`tail -r`.仍然不是万无一失,但这可以提高工作的可能性. (8认同)
  • 为什么不`tac myfile.txt` - 我错过了什么? (4认同)
  • 您需要进行适当的测试,以查看tac是否可用。如果`tac`可用,但RAM用完并在消耗大量输入流的过程中进行交换,会发生什么情况。它失败了,然后`tail -r`成功处理了剩余的流,给出了错误的结果。 (3认同)

小智 41

tac <file_name>
Run Code Online (Sandbox Code Playgroud)

例:

$ cat file1.txt
1
2
3
4
5

$ tac file1.txt
5
4
3
2
1
Run Code Online (Sandbox Code Playgroud)


Yak*_*dry 41

在你的命令结束时: | tac

tac完全符合您的要求,它"将每个文件写入标准输出,最后一行写入."

tac与猫相反:-).

  • 这应该是公认的答案.羞耻上面有这么多的选票. (4认同)
  • 顺便说一句:如果它来自文件,则不必通过管道传输到 tac。您可以简单地“tac filename.ext”(“cat filename.ext”的反向) (2认同)

小智 24

请尝试以下命令:

grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"
Run Code Online (Sandbox Code Playgroud)

  • 为什么不使用"nl"代替grep -n? (2认同)
  • @GoodPerson,默认情况下`nl`将无法为空行编号.`-ba`选项在某些系统上可用,不是通用的(虽然我希望它不会出现HP/UX),而`grep -n`将始终编号*每行*匹配(在这种情况为空)正则表达式. (2认同)
  • 我使用 `cut -d: -f2-` 而不是 gawk (2认同)

kon*_*box 16

Just Bash :)(4.0+)

function print_reversed {
    local lines i
    readarray -t lines

    for (( i = ${#lines[@]}; i--; )); do
        printf '%s\n' "${lines[i]}"
    done
}

print_reversed < file
Run Code Online (Sandbox Code Playgroud)

  • +1为bash和O(n)中的答案,以及不使用递归(如果可以的话,为+3) (2认同)
  • 用包含 `-nenenenenenene` 行的文件试试这个,看看人们推荐总是使用 `printf '%s\n'` 而不是 `echo` 的原因。 (2认同)

小智 11

最简单的方法是使用该tac命令.taccat反过来的.例:

$ cat order.txt
roger shah 
armin van buuren
fpga vhdl arduino c++ java gridgain
$ tac order.txt > inverted_file.txt
$ cat inverted_file.txt
fpga vhdl arduino c++ java gridgain
armin van buuren
roger shah 
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么这个答案出现在下面的答案之前,但它是 http://stackoverflow.com/a/742485/1174784 的骗局 - 这是几年前发布的。 (2认同)

Tim*_*ies 9

我真的很喜欢" 尾巴 "答案,但我最喜欢的gawk答案是....

gawk '{ L[n++] = $0 } 
  END { while(n--) 
        print L[n] }' file
Run Code Online (Sandbox Code Playgroud)


lac*_*der 9

对于可能tac在 shell 脚本中使用的跨操作系统(即 OSX、Linux)解决方案,请使用上面提到的自制软件,然后像这样使用别名 tac:

安装库

对于 MacOS

brew install coreutils
Run Code Online (Sandbox Code Playgroud)

对于 linux debian

sudo apt-get update
sudo apt-get install coreutils 
Run Code Online (Sandbox Code Playgroud)

然后添加别名

echo "alias tac='gtac'" >> ~/.bash_aliases (or wherever you load aliases)
source ~/.bash_aliases
tac myfile.txt
Run Code Online (Sandbox Code Playgroud)


Mar*_*oth 9

如果你想就地修改文件,你可以运行

sed -i '1!G;h;$!d' filename
Run Code Online (Sandbox Code Playgroud)

这样就不需要创建临时文件,然后删除或重命名原始文件,并且具有相同的结果。例如:

$tac file > file2
$sed -i '1!G;h;$!d' file
$diff file file2
$
Run Code Online (Sandbox Code Playgroud)

基于ephemient 的答案,它几乎但不完全是我想要的。