为什么将 HEREDOC 作为字符串传递给“ruby -e”不起作用?

为什么将 HEREDOC 作为字符串传递给“ruby -e”不起作用?

由于我不明白的原因,似乎不可能将定界文档作为表达式传递给 Ruby 解释器:

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

ruby: no code specified for -e (RuntimeError)

同样的事情也发生在 Perl 上,令人痛苦的是,它与 Ruby 毫无关系。

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

即使有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 ...]

如何将定界符作为表达式传递给 Ruby? (或 Perl,或 Sed...)

答案1

这是因为创建一个巨大的字符串并将其作为参数传递并不是“此处文档”所做的。他们创建一个流,可以连接到某些作业的输入。

具体来说,

cat <<!
foo
!

不等于

cat foo

说到这里cat,它可以帮助我们。警告:使用cat以下无用!

echo $(cat <<!
foo
!
)

瞧,我们传递此处文档作为参数,这要归功于应用于cat已提供此处文档的命令替换。

答案2

尝试这个:

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

您必须使用双引号来perl了解要运行的程序,并bash展开此处的文档。

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

您可以看到,perl您的输入仅作为字符串。

catprocess substitution

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

答案3

-e需要一个参数,即要执行的代码。您可以使用嵌入换行符的字符串。这对我来说是最具可读性的。适用于 ruby​​、perl、sed ...

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

您可以通过 stdin 将 ruby​​/perl 代码传递给解释器,但是您不能传递任何文件名参数,也不能从 stdin (*) 读取数据

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

(*) 这太恶心了:你可以发送程序stdin 上的数据,使用 ruby​​ 的(和 Perl 的)DATA 文件句柄:

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

相关内容