Использование того же файла, что и для stdin и stdout, приводит к пустому файлу

Если хотите отфильтровать файл, но если я использую тот же файл, что и для ввода и вывода, выходной файл будет пустым. Есть ли другое решение вместо использования второго файла?

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

1 ответ

Решение

Когда вы открываете файл для записи с >, оно обрезается еще до того, как вы его прочитаете. Вот почему он пуст.

Альтернатива с временным файлом (да, это довольно часто):

php -r "…" < build/index.php > tmp
mv tmp build/index.php

В идеале использовать mktemp создать уникальный временный файл:

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

Но это на самом деле не короче и не лаконичнее.


Мой личный фаворит sponge Утилита от moreutils - она ​​читает ввод и затем записывает в файл:

php -r "…" < build/index.php | sponge build/index.php

Или, что еще лучше, не делайте подстановку в PHP, а используйте инструмент, который поддерживает редактирование на месте, например, Perl с:

perl -pi -e '…' build/index.php

Похоже на sedздесь флаг на месте для GNU sed:

sed -i -e '…' build/index.php

И для BSD sedвам нужен явный пустой аргумент для -i:

sed -i '' -e '…' build/index.php

Возможно, вам придется адаптировать вашу команду регулярного выражения / подстановки для синтаксиса Perl и sed соответственно.

Другие вопросы по тегам