使用与 stdin 和 stdout 相同的文件会导致空文件

Bob*_*Bob 2 linux shell command-line stdout stdin

如果要过滤文件,但如果我使用相同的文件作为输入和输出,则输出文件为空。是否有另一种解决方案而不是使用第二个文件?

php -r "echo preg_replace('~/\* DEV \*/(.*)/\* ENDDEV \*/~si', '', file_get_contents('php://stdin'));" < build/index.php > build/index.php
Run Code Online (Sandbox Code Playgroud)

slh*_*hck 6

当您使用 来打开一个文件进行写入时>,它甚至在您阅读它之前就被截断了。这就是为什么它是空的。

使用临时文件的替代方法(是的,这很常见):

php -r "…" < build/index.php > tmp
mv tmp build/index.php
Run Code Online (Sandbox Code Playgroud)

理想情况下,用于mktemp生成唯一的临时文件:

tmp="$(mktemp /tmp/file.XXX)"
php -r "…" < build/index.php > "$tmp"
mv "$tmp" build/index.php
Run Code Online (Sandbox Code Playgroud)

但这并不是更短或更简洁。


我个人最喜欢的是moreutilssponge实用程序——它读取输入然后写入文件:

php -r "…" < build/index.php | sponge build/index.php
Run Code Online (Sandbox Code Playgroud)

或者,更好的是,不要在 PHP 中进行替换,而是使用支持就地编辑的工具,例如 Perl:

perl -pi -e '…' build/index.php
Run Code Online (Sandbox Code Playgroud)

与 类似sed,这里是 GNU 的就地标志sed

sed -i -e '…' build/index.php
Run Code Online (Sandbox Code Playgroud)

对于 BSD sed,您需要一个明确的空参数-i

sed -i '' -e '…' build/index.php
Run Code Online (Sandbox Code Playgroud)

您可能需要分别针对 Perl 和 sed 的语法调整正则表达式/替换命令。