唯一排序:将输出重定向到同一文件


14

有什么短的方法可以将管道输出保存到已处理的相同文件中。例如,这就是我实际上在做的

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

我想知道是否有一种方法可以仅在一行中执行此操作(不使用&&附加这些命令)

这不是方法,而是一个想法

$ cat filename | sort | uniq > filename

2
echo $(cat filename | sort | uniq > result) > filename或者其他的东西 ?只是路过,我没有时间尝试。
MrVaykadji

Answers:


18

您可以spongemoreutils包中使用:

LC_ALL=C sort -u filename | sponge filename

您也不需要管道到uniq,因为sort-u在排序可以选择唯一的行。

请注意,在具有UTF-8语言环境的GNU系统上,sort -u或者sort | uniq没有给您唯一的行,而是行序列中的第一个在当前语言环境中对它们进行排序的行。

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

只给了你。将语言环境更改为C会强制基于字节值的排序顺序:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq


12

您不需要像cat和这样的任何额外命令uniq,也无需使用rm命令和mv命令来删除和重命名文件名。只需使用简单的命令。

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

它是如何工作的?

sort命令对文件名进行排序,并带有-u选项,从中删除重复的行。然后with -o选项使用place方法将输出写入同一文件。


3
如果在sort运行时系统崩溃,则将丢失原始文件。
cuonglm

@Gnouc所以,这是不幸的结局!:'(
–αғsнιη14Sep 26'11

1
谢谢!在此示例中,尤其是“ sort”,我应该这样做。但是我在考虑一个一般情况。@Gnouc,哈哈没有办法认为,如果这不是发生在您身上,对吗?
whitenoisedb

3

建议的示例(如下)不起作用,因为您实际上是在同时读取和写入同一文件。

$ cat filename | sort | uniq > filename

管道或重定向的想法是,每个管道或重定向左侧和右侧的命令同时并行运行。当左边的命令仍在运行时,右边的命令会处理从左边的命令移交给它的信息。

为了使您的方案能够正常工作,从文件中读取的命令需要在写入文件的命令开始之前完成。为了使其正常工作,您需要首先将输出重定向到一个临时位置,然后完成该操作,将其从该临时位置发送回文件中。

更好的方法基本上与您之前的示例类似,在该示例中,您重定向到一个临时文件,然后将该文件重命名为原始文件(除非您不需要先删除该文件,因为移动会删除任何现有目标) 。

$ cat filename | sort | uniq > result
$ mv -f result filename

您也可以将其保存到字符串变量中,除非仅当数据足够小以一次全部放入内存时才起作用。


正如有人建议编辑一样,您可以将其更改cat filename | sort为“正义” sort filename- cat在此是不必要的。
托马斯

我下面的示例不是做到这一点的方法。感谢您的澄清。cat在这种情况下可能是不必要的,但我专注于重定向部分。
whitenoisedb

1
我正在解释为什么您下面的示例不起作用。我知道您知道它不起作用。
托马斯

感谢您的澄清!实际上,我不知道真正发生了什么。
whitenoisedb

2

您可以使用以下tee命令:

sort -u filename | tee filename > /dev/null

tee命令从标准输入读取并写入标准输出文件。


2
这对我不起作用。
pjvandehaar,2015年


确实对我有用。例如,将一行移动到文件底部:(cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/null有效。就像原始帖子一样,如果您> ~/file没有,这将不起作用tee。Tee在这里类似于sort -o file,它在不继续相同管道的情况下写入命名文件。
约书亚·戈德堡

等一下,对不起! 我从经验上已经看到,这会意外地丢失数据,如@Steven的链接中所述。在9行上制作数字1..9的文件。以下内容将运行几次,然后偶尔从文件中删除所有数据:(cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x 我建议使用临时文件,mv或者建议使用@Steven 链接中的解决方案。
Joshua Goldberg

@JoshuaGoldberg在此页面上看到我的答案了吗?
史蒂文·彭妮

0

您可以在Ex模式下使用Vim:

ex -sc 'sort u|x' filename
  1. sort u 排序独特

  2. x 写(如果有)更改并退出

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.