我如何执行任何命令编辑其文件(参数)“到位”使用bash?

我有一个文件temp.txt,我想sort在bash sort命令。

我想sorting的结果来replace原来的文件。

这不起作用,例如(我得到一个空的文件):

 sortx temp.txt > temp.txt 

这可以在一行中完成,而无需复制到临时文件?


编辑: -o选项是非常酷的sort 。 我用我的问题作为例子。 我遇到了与其他命令相同的问题:

 uniq temp.txt > temp.txt. 

有更好的通用解决scheme吗?

 sort temp.txt -o temp.txt 

sort需要看到所有的input,才能开始输出。 出于这个原因, sort程序可以很容易地提供一个选项来就地修改文件:

 sort temp.txt -o temp.txt 

具体来说, GNU sort的文档说:

通常情况下,sorting在打开输出文件之前读取所有input,因此您可以使用命令sort -o FFcat F | sort -o F cat F | sort -o F 然而,用--merge-msort可以在读取所有input之前打开输出文件,所以像cat F | sort -m -o F - G这样的命令 cat F | sort -m -o F - G不安全,因为sorting可能会在cat完成读取之前开始写入F

虽然BSD的文档说:

如果输出文件是input文件之一,则在sorting之前将其sorting复制到临时文件,然后将输出写入输出文件。

诸如uniq命令可以在完成读取input之前开始写入输出。 这些命令通常不支持就地编辑(并且这将更难支持此function)。

您通常使用临时文件解决此问题,或者如果您绝对要避免使用中间文件,则可以在写出之前使用缓冲区来存储完整结果。 例如,用perl

 uniq temp.txt | perl -e 'undef $/; $_ = <>; open(OUT,">temp.txt"); print OUT;' 

在这里,perl部分从variables$_读取uniq的完整输出,然后用这些数据覆盖原始文件。 你可以在你select的脚本语言中做同样的事情,甚至可以在Bash中使用。 但是请注意,它将需要足够的内存来存储整个文件,这在处理大文件时不可取。

这里有一个更一般的方法,使用uniq,sort和whatnot。

 { rm file && uniq > file; } < file 

东武对海绵认股权证的评论本身就是一个答案。

引用moreutils主页:

目前为止,最常用的工具是sponge(1),它可以让你做这样的事情:

 % sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd 

然而, sponge遭受同样的问题Steve Jessop在这里评论。 如果sponge前的pipe道中有任何命令失败,则原始文件将被覆盖。

 $ mistyped_command my-important-file | sponge my-important-file mistyped-command: command not found 

呃, my-important-file已经没有了。

在这里,一行:

 sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt 

从技术上讲,没有复制到临时文件,“mv”命令应该是即时的。

我喜欢sort file -o file答案,但不想input相同的文件名两次。

使用BASH 历史扩展 :

 $ sort file -o !#^ 

抓取当前行的第一个参数。

独特的sorting:

 $ sort -u -o file !#$ 

抓取当前行中的最后一个参数。

许多人提到了-o选项。 这是man page部分。

从手册页:

  -o output-file Write output to output-file instead of to the standard output. If output-file is one of the input files, sort copies it to a temporary file before sorting and writing the output to output- file. 

另一种sponge更常见的sed

 sed -ni r<(command file) file 

它适用于任何命令( sortuniqtac ,…),并使用非常有名的sed-i选项 (就地编辑文件)。

警告:先尝试command file因为就地编辑文件本质上不安全。


说明

首先,你告诉sed不要打印(原始)行( -n选项 ),并且在sedr命令和bash的进程replace的帮助下 ,由<(command file)生成的内容将是输出保存到位


让事情变得更容易

你可以把这个解决scheme包装成一个函数:

 ip_cmd() { # in place command CMD=${1:?You must specify a command} FILE=${2:?You must specify a file} sed -ni r<("$CMD" "$FILE") "$FILE" } 

 $ cat file d b c b a $ ip_cmd sort file $ cat file a b b c d $ ip_cmd uniq file $ cat file a b c d $ ip_cmd tac file $ cat file d c b a $ ip_cmd bash: 1: You must specify a command $ ip_cmd uniq bash: 2: You must specify a file 

这会受到很大的内存限制,但是您可以使用awk将中间数据存储在内存中,然后将其写回。

 uniq temp.txt | awk '{line[i++] = $0}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt 

使用参数--output=-o

刚刚在FreeBSD上试过:

 sort temp.txt -otemp.txt 

要添加uniqfunction,有什么缺点:

 sort inputfile | uniq | sort -o inputfile 

请阅读非交互式编辑器, ex

如果你坚持使用sort程序,你必须使用中间文件 – 我不认为sort有内存中的sorting选项。 任何其他的标准input/标准输出技巧都会失败,除非你可以保证sort的stdin的缓冲区大小足够大以适应整个文件。

编辑:我的耻辱。 sort temp.txt -o temp.txt作品优秀。

另一个scheme

 uniq file 1<> file