我有一堆包含许多空白行的文件,并希望删除任何重复的空行以使文件更容易阅读。我写了以下脚本:
#!/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' *
如果您同时写入文件,则无法从文件中读取。 >
重定向首先清除文件,因此没有什么可读的。
您可以使用sed -i -e '/^$/d'
删除空行(如果您的sed支持-i
),这会在引擎盖下创建临时文件。