Bash 文件重定向的工作方式与脚本不同

Bash 文件重定向的工作方式与脚本不同
$ cat test.txt
foo
bar

此 sed 命令将 text.txt 的第一行替换为“baz”。它在命令行中运行良好:

$ sed "1s%.*%baz%" "test.txt" > "test.txt"
$ cat test.txt
baz
bar

我希望能够将该 sed 命令放入名为test.sh如下内容的脚本中:

#!/bin/sh
sed "1s%.*%baz%" "test.txt" > "test.txt"

但是,当我运行它时./test.sh,它会删除 text.txt 中的所有行(text.txt 被完全清空)?!

有任何想法吗?

答案1

您无法(安全地)将命令的输出重定向到它正在读取的文件。您很幸运,它恰好可以从命令行运行。可能在一种情况下,sed在 shell 破坏它之前能够读取整个文件,而在另一种情况下则不能。这种差异可能是由于某些缓冲问题造成的,但这并不值得弄清楚。

如果您想就地修改文件,您应该将输出写入临时文件,然后(如果成功)将临时文件重命名为输入文件的名称。

例如:

sed "1s%.*%baz%" test.txt > $$ && mv $$ test.txt

$$是当前 shell 的进程 ID;这是获取合理唯一文件名的便捷方式。或者,即使您没有同名文件test.txt.$$,也可以使用 或。tmp

在命令的特定情况下sed,您可以使用-i选项就地修改文件 - 但这只会导致sed在内部创建一个临时文件。语法,甚至-i选项的存在,可能会因实现的不同而不同sed;请查看您的本地文档。

相关内容