我有一堆包含许多空白行的文件,并且想要删除任何重复的空白行以使读取文件更容易。我编写了以下脚本:
#!/bin/bash
for file in * ; do cat "$file" | sed 's/^ \+//' | cat -s > "$file" ; done
但是,这产生了非常不可靠的结果,大多数文件完全变空,只有少数文件具有预期结果。更重要的是,每次我重试时,有效的文件似乎都会随机变化,因为每次运行都会正确编辑不同的文件。这是怎么回事?
注意:这更多的是一个理论问题,因为我意识到我可以使用如下解决方法:
#!/bin/bash
for file in * ; do
cat "$file" | sed 's/^ \+//' | cat -s > "$file"-tmp
rm "$file"
mv "$file"-tmp "$file"
done
但这似乎不必要地令人费解。那么为什么“直接”方法如此不可靠呢?
最佳答案
发生不可预测性的原因是管道中的两个阶段(cat "$file"
和 cat -s > "$file"
)之间存在竞争条件。
第一个尝试打开文件并从中读取,而另一个尝试清空文件。
- 如果在读取之前已清空,您将得到一个空文件。
- 如果在清空之前读取它,您将获得一些数据(但文件很快就会被清空,并且结果会被截断,除非它非常短)。
如果您有 GNU sed,则只需执行 sed -i 'expression' *
关于bash - 为什么在管道中读取和写入同一文件会产生不可靠的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20620966/