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

577
Bob

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

php -r "echo preg_replace('~/\* DEV \*/(.*)/\* ENDDEV \*/~si', '', file_get_contents('php://stdin'));" < build/index.php > build/index.php 
2
использовать файл в качестве основы, затем создать новый, удалить оригинал и переименовать новый, я не думаю, что вариант. это также может быть полезно в качестве резервной копии, так как вы редактируете конфиденциальный файл (индекс) Lorenzo Von Matterhorn 10 лет назад 0
Это определенно вариант, но должен быть другой, более чистый путь. Bob 10 лет назад 0
Я вполне уверен, что на самом деле нет более чистого способа, так как даже программы с опцией 'edit in place', такие как `sed`, * фактически * создают временные файлы и затем перезаписывают. evilsoup 10 лет назад 2

1 ответ на вопрос

5
slhck

When you open a file for writing with >, it is truncated before you even read it. That's why it's empty.

Alternative with a temporary file (yes, this is quite common):

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

Ideally, use mktemp to generate a unique temporary file:

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

But this isn't really shorter or more concise.


My personal favorite is the sponge utility from moreutils – it reads input and then writes to the file:

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

Or, better yet, don't do the substitution in PHP, but a tool that supports in-place editing, like Perl with:

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

Similar with sed, here the in-place flag for GNU sed:

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

And for BSD sed, you need an explicit empty argument for -i:

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

You will probably have to adapt your regular expression / substitution command for Perl's and sed's syntax, respectively.

Или sed, если есть опция `-i`. Bobby 10 лет назад 0
Вероятно, следует использовать `mktemp` для временного файла. Daniel Beck 10 лет назад 0
@Daniel Конечно - добавил это. ОП хотел что-то «чистое», поэтому я не решался добавить еще больше кода, когда реальным решением является, например, использование правильного инструмента. slhck 10 лет назад 0

Похожие вопросы