排序是否支持按原样对文件进行排序,例如`sed --in-place`?


80

我是盲人还是没有像这样的--in-place选择sort

为了将结果保存到输入文件中,sed使用-i--in-place)。

将输出重定向sort到输入文件

sort < f > f

导致将其清空。如果没有--in-place选择-也许有一些技巧可以方便地做到这一点?

(我唯一想到的是:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

移动不是正确的选择,因为可能会更改文件权限。这就是为什么我用临时文件的内容覆盖的原因,然后将其删除。)


还有insitu,允许就地使用任何命令。
sr_

@sr_,这是一个有趣的命令,但是它不适用于任何命令,只有那些写入速度不比读取速度快的命令(否则,它将在命令读取之前破坏输入文件)。无法保证与一起使用sort
cjm 2012年

@cjm,我真的不知道,但没有应该处理这种情况?
sr_ 2012年

@sr_,我认为您是对的。我阅读了说明,而不是查看源代码。虽然对于真正的大文件,它可能会耗尽缓冲区的内存并崩溃(它看起来并不像从malloc检查NULL返回)。
cjm 2012年

@cjm:的确是这样。
sr_ 2012年

Answers:


110

sort具有-o, --output以文件名作为参数的选项。如果它与输入文件相同,则将结果写入一个临时文件,然后覆盖原始输入文件(与输入文件完全相同sed -i)。

GNU sort信息页面:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

以及来自Open Group基本规范第7期

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.

没错!有用 !我看不到任何线索man sort-它是未公开的功能吗?它是标准便携式的吗?
Grzegorz Wierzowiecki 2012年

@GrzegorzWierzowiecki:参见更新。
enzotib 2012年

好的答案:)。
Grzegorz Wierzowiecki,2012年

1
总结:sort -o <filename> <filename>将文件安全地排序到位。
菲特

11

您可以使用该sponge函数,该函数先浸泡stdin,然后将其写入文件,例如:

sort < f | sponge f

缺点sponge是它将输出临时存储在内存中,这对于大文件可能是有问题的。否则,您必须先将其写入文件,然后再覆盖原始文件。

但是,正如其他答案所指出的那样,一般而言,修改并不是一个好主意,因为在进程(例如一个进程)的中间sponge,计算机可能崩溃,然后您可能会丢失原始文件和新文件。您最好先将其写入另一个文件,然后再使用原子mv(移动)指令。


7

用输出文件覆盖输入文件是很危险的,因为如果在写入文件时程序或系统崩溃,则两者都会丢失。

一些程序(主要是GNU版本)具有就地选项(例如,-i在perl和GNU sed上;-o在GNU排序上)。他们通过将数据放入临时文件然后将其移动到适当位置来进行工作。对于没有此类选项sponge程序Colin Watson的实用程序(包括在Joey Hess的moreutils中)可以安全地执行任何程序的工作(例如:我可以cut在适当的位置更改文件吗;; 如何使iconv用转换后的文件替换输入文件)输出?)。

只有在极少数情况下,您无法使用相同的权限重新创建原始文件时,我才建议覆盖该文件。在这种情况下,最好将原始输入保存在某个地方。然后,您可以简单地处理输入的副本并将其发送到原始文件中。

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional

1
sort -o不是特定于GNU的,并且经过专门设计以在适当的地方覆盖文件。sort在完全读取输入(使用内存或临时文件存储数据)之前无法开始写入其输出,因此很自然地应该能够覆盖其输入。
斯特凡Chazelas

实际上,这是一种情况,其中GNU sort不是POSIX,因为sort -mo file1 file1 file2不能保证GNU 不能工作,而传统sorts知道如何解决该问题(在70年代的Unix V7中已经存在)。
斯特凡Chazelas

@JoelCross Odd sort -o与coreutils 8.25一起为我工作,并且该属性在手册中进行了记录(请注意,这仅在排序时出现,而在合并时才发生)。如果可以重现此错误,请发送错误报告(指示确切的命令行,确切的输入文件,正在其上运行的系统以及如何获取二进制文件)。
吉尔斯

4

使用-o或尝试vim-way:

$ ex -s +'%!sort' -cxa file.txt
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.