Por que passar um HEREDOC como uma string para 'ruby -e' não funciona?

2

Por razões que eu não entendo, parece impossível passar um heredoc como uma expressão para um interpretador Ruby:

$ ruby -e <<END
heredoc> puts 'hi'
heredoc> END

ruby: no code specified for -e (RuntimeError)

A mesma coisa acontece com o Perl, para tornar dolorosamente óbvio que não tem nada a ver com o Ruby.

$ perl -e<<END
heredoc> print 'hi'
heredoc> END
No code specified for -e.

E mesmo com sed :

$ echo "blah" | sed -e <<END
pipe heredoc> s/.*/Hi/
pipe heredoc> END
sed: option requires an argument -- e
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]

Como posso passar um heredoc como uma expressão para Ruby? (ou Perl, ou Sed ...)

    
por iconoclast 16.07.2014 / 05:36

3 respostas

5

É porque criar uma corda gigante e passá-la como argumento não é o que "documentos aqui" fazem. Eles criam um fluxo, que pode ser conectado à entrada de algum trabalho.

Concretamente,

cat <<!
foo
!

não é equivalente a

cat foo

.

Falando de cat , isso pode nos ajudar aqui. Aviso: o uso inútil não - de cat segue!

echo $(cat <<!
foo
!
)

Veja, nós podemos passar um documento aqui como um argumento, graças à substituição de comando aplicada a cat que foi alimentado com um documento aqui.

    
por 16.07.2014 / 06:06
1

Tente isto:

$ perl -e "$(cat <<'EOF'
print 'qwerty';
EOF
)"
qwerty

Você deve usar aspas duplas para perl para saber qual programa executar e bash para expandir o documento aqui.

$ perl -MO=Deparse -e "<<'EOF'
print 'qwerty';
EOF
"
'???';
-e syntax OK

Você pode ver, perl ver sua entrada apenas como string.

Com cat e process substitution :

$ perl -MO=Deparse -e "$(cat <<'EOF'
print 'qwerty';
EOF
)
"
print 'qwerty';
-e syntax OK
    
por 16.07.2014 / 06:12
1

-e requer um argumento, o código a ser executado. Você pode usar uma string com novas linhas incorporadas. Isso para mim é o mais legível. Funciona com ruby, perl, sed ...

ruby -e '
  1.upto(10) do |n|
    p [n, n.even?]
  end
'

Você pode passar o código ruby / perl para o interpretador via stdin, mas você não pode passar nenhum argumento de nome de arquivo, nem pode ler dados de stdin (*)

ruby <<'END'
  1.upto(10) do |n|
    p [n, n.even?]
  end
END

(*) isso é bem grosseiro: você pode enviar o programa e os dados em stdin, usando o filehandle de ruby (e perl):

{
    cat <<'END'
while (<DATA>) {print +(split /:/)[0], "\n"}
__END__
END
    cat /etc/passwd
} | perl
    
por 28.07.2015 / 21:37