我如何执行任何命令编辑其文件(参数)“到位”使用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 FF
和cat F | sort -o F
cat F | sort -o F
然而,用--merge
(-m
)sort
可以在读取所有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
它适用于任何命令( sort
, uniq
, tac
,…),并使用非常有名的sed
的-i
选项 (就地编辑文件)。
警告:先尝试command file
因为就地编辑文件本质上不安全。
说明
首先,你告诉sed
不要打印(原始)行( -n
选项 ),并且在sed
的r
命令和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
要添加uniq
function,有什么缺点:
sort inputfile | uniq | sort -o inputfile
请阅读非交互式编辑器, ex
如果你坚持使用sort
程序,你必须使用中间文件 – 我不认为sort
有内存中的sorting选项。 任何其他的标准input/标准输出技巧都会失败,除非你可以保证sort的stdin的缓冲区大小足够大以适应整个文件。
编辑:我的耻辱。 sort temp.txt -o temp.txt
作品优秀。
另一个scheme
uniq file 1<> file