来自moreutils的海绵-外壳重定向有什么区别?有用的例子?


16
> brew install moreutils                                                          
==> Downloading https://homebrew.bintray.com/bottles/moreutils-0.55.yosemite.bottle.tar.gz    
######################################################################## 100.0%               
==> Pouring moreutils0.55.yosemite.bottle.tar.gz       
🍺  /usr/local/Cellar/moreutils/0.55: 67 files, 740K   

海绵读取标准输入并将其写到指定文件中。与Shell重定向不同,海绵在写入输出文件之前先吸收所有输入。这允许构造读取和写入同一文件的管道。

我不明白 请给我一些有用的例子。

什么吸收了是什么意思?



另一个例子是expand foo.txt | sponge foo.txt。另请参阅:stackoverflow.com/a/33639324/1959808
Ioannis Filippidis

tl; dr 截断输出文件之前sponge “吸收”其输入
BallpointBen

Answers:


33

假设您有一个名为的文件input,您想删除所有以#in 开头的行input。您可以得到所有的开头都不是#使用:

grep -v '^#' input

但是,您如何进行更改input?使用标准的POSIX工具集,您需要使用一个临时文件,例如:

grep -v '^#' input >/tmp/input.tmp
mv /tmp/input.tmp ./input

使用shell重定向:

grep -v '^#' input >input

input在您阅读之前将被截断。

使用sponge,您可以:

grep -v '^#' input | sponge input

4
实际上,只要使用<>运算符对字节进行转换,就可以安全地同时读写文件。
克里斯·

@ChrisDown:是的,我的意思是不作掩饰
cuonglm

我不确定您对“使其腐败”的含义。不同于><<>除非确实出错,否则不会损坏文件。您可以很容易地使用它逐字节写入。例如,尝试与结合使用tr
克里斯·

@ChrisDown:让我删除该句子以避免混淆。我的意思是,使用时<>file,您打开文件进行读写,但实际上不向文件写入任何内容。
cuonglm

1
我认为@ChrisDown试图提出的要点是<>不会截断文件,而只是用新的输出替换其现有字节。如果新的输出太短,则在文件末尾会有剩余的垃圾。但是,如果新的输出足够长,就没有风险了。
BallpointBen

8

moreutils主页本身记录了典型的用例:

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

在这里,/ etc / passwd都被写入和读取,并且正在被修改。如果在写入前不加紧stdin,/ etc / passwd可能会损坏(因为在读取过程中文件已更改)。


如果它能解释您的操作方式,那么这将是moreutils页面上的一个很好的例子:-)
Br.Bill
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.