É PHP, claro. Pipes não comeria o primeiro caractere do arquivo. O PHP está lendo todos os caracteres, mas não está exibindo o primeiro. Até agora você não pode dizer se o problema está na entrada ou na saída: pode ser que o PHP não esteja exibindo o primeiro caractere por algum motivo.
Um pequeno experimento mostra que o problema é de fato com a entrada.
$ php <(echo '<?php echo "hello" ?>')
?php echo "hello" ?>
$ php <(echo ' <?php echo "hello" ?>')
hello$
O PHP está consumindo o primeiro caractere do script, somente quando o script é dado por um nome de arquivo (não quando não há nenhum argumento de linha de comando e o script é lido a partir da entrada padrão), somente quando o arquivo de script é um pipe ou outro arquivo não pesquisável (não quando o arquivo de script é procurado, por exemplo, quando é um arquivo normal).
O que está acontecendo é que no início, antes que o analisador PHP normal entra em ação, o processador da linha de comando verifica se o script começa com um shebang linha. Se o script começar com os dois caracteres #!
, o PHP pula a primeira linha. Desta forma você pode escrever um script PHP como este
#!/usr/bin/php
first line
<?php echo "second line"?>
e esse script será exibido
first line
second line
e nenhum espúrio #!/usr/bin/php
no começo.
O detector de shebang funciona assim:
- Leia o primeiro caractere.
- Se o primeiro caractere for
#
, leia outro caractere. - Se os dois primeiros caracteres forem
#!
, continue lendo até o primeiro caractere de nova linha. - Se os dois primeiros caracteres não forem
#!
, retroceda até o início do arquivo. - Inicie a análise normal do PHP.
Se o arquivo de script não for pesquisável, a etapa de retrocesso falhará, mas o PHP não tentará detectar isso, então o primeiro caractere do arquivo será perdido (e também o segundo caractere se o primeiro for um #
). Este é um bug no interpretador de linha de comando do PHP.
Você pode ver o código para você mesmo (na função cli_seek_file_begin
).