有没有简单的方法可以将管道输出保存到与其处理相同的文件中。例如,这就是我实际正在做的事情
$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename
我想知道是否有办法只用一行完成此操作(不使用 && 附加这些命令)
这不是办法,但可以得到一个想法
$ cat filename | sort | uniq > filename
答案1
您可以sponge
使用更多工具包裹:
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
①
②
答案2
您不需要任何额外的命令,例如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
,并使用选项从中删除重复的行。然后使用-o
选项将输出以就地方法写入同一个文件。
答案3
您建议的示例(如下)不起作用,因为您实际上是同时读取和写入同一个文件。
$ cat filename | sort | uniq > filename
管道或重定向的理念是,每个管道或重定向左侧和右侧的命令同时并行运行。右侧的命令处理左侧命令交给它的信息,而左侧的命令仍在运行。
为了使您的方案能够正常工作,从文件读取的命令需要在写入文件的命令开始之前完成。为了使其正常工作,您需要先将输出重定向到临时位置,然后在完成后将其从临时位置发送回文件。
更好的方法基本上就像您前面的例子一样,您重定向到一个临时文件,然后将该文件重命名为原始文件(除了您不需要先删除该文件,因为移动会删除任何现有目标)。
$ cat filename | sort | uniq > result
$ mv -f result filename
您也可以将其保存到字符串变量中,但这仅当数据足够小,可以一次全部放入内存中时才有效。
答案4
你可以在 Ex 模式下使用 Vim:
ex -sc 'sort u|x' filename
sort u
唯一排序x
写下是否做出了改变(他们确实做出了改变)并退出