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

Upg*_*ave 1 bash sed

$ cat test.txt
foo
bar
Run Code Online (Sandbox Code Playgroud)

此 sed 命令将 text.txt 中的第一行替换为“baz”。它从命令行工作正常:

$ sed "1s%.*%baz%" "test.txt" > "test.txt"
$ cat test.txt
baz
bar
Run Code Online (Sandbox Code Playgroud)

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

#!/bin/sh
sed "1s%.*%baz%" "test.txt" > "test.txt"
Run Code Online (Sandbox Code Playgroud)

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

有任何想法吗?

Kei*_*son 6

您不能(安全地)将命令的输出重定向到它正在读取的文件。你很“幸运”,它碰巧从命令行工作。可能在一种情况下sed能够在外壳破坏它之前读取整个文件,而在另一种情况下则不能。差异可能是由于某些缓冲问题造成的,但实际上并不值得弄清楚。

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

例如:

sed "1s%.*%baz%" test.txt > $$ && mv $$ test.txt
Run Code Online (Sandbox Code Playgroud)

$$是当前shell的进程ID;这是获取合理唯一文件名的便捷方法。或者您可以使用,例如,test.txt.$$,或者即使tmp您没有具有该名称的东西。

sed命令的特殊情况下,您可以使用该-i选项就地修改文件——但这只会导致sed在内部创建一个临时文件。语法,甚至存在,如果-i选项可以从一种sed实现到另一种实现不同;检查您的本地文档。