Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Ruby中的unix管道中使用$stdout和$stdin?_Ruby_Awk_Pipe_Stdout_Stdin - Fatal编程技术网

如何在Ruby中的unix管道中使用$stdout和$stdin?

如何在Ruby中的unix管道中使用$stdout和$stdin?,ruby,awk,pipe,stdout,stdin,Ruby,Awk,Pipe,Stdout,Stdin,我可以创建如下ruby可执行文件(虚拟示例): 然后,我可以将此文件用于其他unix工具: echo "a\nb\nc\nd" | ./pipes.rb | head -n2 # A # B 但是如果我需要用另一个对awk的调用来扩展虚拟示例,那么它就不起作用了: echo '#!/usr/bin/env ruby puts %x[awk ''{print toupper($1)}'' #{STDIN} | awk ''{ \ print tolower($1) \ }'']

我可以创建如下ruby可执行文件(虚拟示例):

然后,我可以将此文件用于其他unix工具:

echo "a\nb\nc\nd" | ./pipes.rb | head -n2
# A
# B
但是如果我需要用另一个对awk的调用来扩展虚拟示例,那么它就不起作用了:

echo '#!/usr/bin/env ruby
    puts %x[awk ''{print toupper($1)}'' #{STDIN} | awk ''{ \
    print tolower($1) \
}'']
' >! pipes2.rb
chmod +x pipes2.rb
echo "a\nb\nc\nd" | ./pipes2.rb | head -n2
# A
# B
# it should be: "a\nb"
问题是
STDIN
被字符串化为:
#
并且散列被解释为注释,因此第二个
awk
语句被忽略(但出于某种原因,
head
命令仍然返回两行):


有办法重构吗?

这里的问题是,您直接提供
$stdin
,而不是使用它做任何事情。这就是Ruby将其呈现为原始对象的原因。它是一个文件句柄,除非你对它使用一个方法,而不是原始数据

您需要的是从该文件句柄获取所有内容:

$stdin.read
如果要使用Ruby,则没有理由使用
awk

#!/usr/bin/env ruby

puts STDIN.read.upcase
如果要将换行保留为
“\n”
,请执行以下操作:

puts STDIN.read.upcase.inspect
如果您承诺使用外部命令:

require 'open3'

Open3.popen3("awk '{print toupper($1)}'") do |cmd_in, cmd_out, cmd_err|
  # Read from our STDIN and push through to the command's STDIN
  cmd_in.write(STDIN.read)

  # Close STDIN on the command to tell it we're finished writing.
  cmd_in.close

  # Read result from command's STDOUT and write to our STDOUT
  puts cmd_out.read.inspect
end

好吧,我找到了一个更简单的方法

require "open3"
Open3.pipeline(
    ["awk '{print toupper($1)}'"],
    ["awk '{print tolower($1)}'"], 
:in => STDIN) # this is redundant, but I might want to change :in in the future

在生产Ruby代码中使用
$stdin
$stdout
有点不寻常,它们是受Perl启发的全局变量。大多数情况下,您会看到使用了
STDIN
STDOUT
STDOUT.put
也是冗余的,因为默认情况下
put
会转到
STDOUT
。好的,我可以使用
STDIN
put
,但结果是一样的。谢谢,但我确实需要使用awk。上档/下档只是一个示例,您确定需要使用
awk
?Ruby没有做不到的事情,而且从
awk
到Ruby的转换通常非常简单。如果您确实需要使用外部命令,是一种让您完全控制输入和输出的方法。这看起来很有趣,有没有一种方法可以组合多个命令(如上面的两个awk调用)?当然,您可以根据需要不断更改in->in,out->out,甚至在需要时嵌套它们。
puts STDIN.read.upcase.inspect
require 'open3'

Open3.popen3("awk '{print toupper($1)}'") do |cmd_in, cmd_out, cmd_err|
  # Read from our STDIN and push through to the command's STDIN
  cmd_in.write(STDIN.read)

  # Close STDIN on the command to tell it we're finished writing.
  cmd_in.close

  # Read result from command's STDOUT and write to our STDOUT
  puts cmd_out.read.inspect
end
require "open3"
Open3.pipeline(
    ["awk '{print toupper($1)}'"],
    ["awk '{print tolower($1)}'"], 
:in => STDIN) # this is redundant, but I might want to change :in in the future