我刚刚跑了
cat /opt/webapplications/Word/readme.log | grep -v 'Apple'
并且我在 CLI 上获得了我所期望的输出,即所有readme.log
不包含“ Apple
”的行...
接下来我跑了……
cat /opt/webapplications/Word/readme.log | grep -v 'Apple' > /opt/webapplications/Word/readme.log
但是,/opt/webapplications/Word/readme.log
是空白的。
谁能向我解释为什么会发生这种情况,或者我应该采取正确的方法来解决这个问题?
答案1
发生这种情况是因为首先>
要创建要写入的文件 - 如果该文件已存在,则其内容将被删除。 (此外,完全没有必要cat
在语句中使用,因为grep
它适用于文件,而不仅仅是 STDIN。)
正确的做法是使用临时文件来读取或写入。因此
cp /opt/webapplications/Word/readme.log /tmp/readme.log
grep -v 'Apple' /tmp/readme.log > /opt/webapplications/Word/readme.log
或者
grep -v 'Apple' /opt/webapplications/Word/readme.log > /tmp/readme.log
mv /tmp/readme.log /opt/webapplications/Word/readme.log
会工作。
答案2
当重定向到同一个文件(>
)时,shell 可能会在cat
调用命令和读取输入之前创建/截断该文件(参见:为什么“sort file1 > file1”不起作用?)。如果要过滤文件,最好将输出重定向到不同的文件,或者完全避免重定向,例如:
grep -v 'Apple' readme.log | tee readme.log
更好、更安全的方法是使用专门为此类操作设计的就地编辑器,例如
sed -i '.bak' '/Apple/d' readme.log
或者使用ex
(Vim 的一部分):
ex +g/Apple/d -cwq readme.log
有关的:
- 删除文本文件中包含特定字符串的行在 SO
- 将文件输入重定向回同一文件在 SO