如何将Ruby脚本的输出管道输出到“head”而不会出现管道错误

时间:2020-12-19 14:08:54

I have a simple Ruby script that looks like this

我有一个简单的Ruby脚本,看起来像这样

require 'csv'
while line = STDIN.gets
  array = CSV.parse_line(line)
  puts array[2]
end

But when I try using this script in a Unix pipeline like this, I get 10 lines of output, followed by an error:

但是当我尝试在这样的Unix管道中使用这个脚本时,我得到10行输出,然后是一个错误:

ruby lib/myscript.rb < data.csv  | head

12080450
12080451
12080517
12081046
12081048
12081050
12081051
12081052
12081054
lib/myscript.rb:4:in `write': Broken pipe - <STDOUT> (Errno::EPIPE)

Is there a way to write the Ruby script in a way that prevents the broken pipe exception from being raised?

有没有办法以防止破坏管道异常的方式编写Ruby脚本?

2 个解决方案

#1


22  

head is closing the standard output stream after it has read all the data it needs. You should handle the exception and stop writing to standard output. The following code will abort the loop once standard output has been closed:

head在读取了所需的所有数据后关闭标准输出流。您应该处理异常并停止写入标准输出。一旦标准输出关闭,以下代码将中止循环:

while line = STDIN.gets
  array = CSV.parse_line(line)
  begin
    puts array[2]
  rescue Errno::EPIPE
    break
  end
end

#2


10  

The trick I use is to replace head with sed -n 1,10p.

我使用的技巧是用sed -n 1,10p替换头部。

This keeps the pipe open so ruby (or any other program that tests for broken pipes and complains) doesn't get the broken pipe and therefore doesn't complain. Choose the value you want for the number of lines.

这使得管道保持打开状态,因此ruby(或任何其他测试管道损坏和抱怨的程序)不会破坏管道,因此不会抱怨。选择所需的行数。

Clearly, this is not attempting to modify your Ruby script. There almost certainly is a way to do it in the Ruby code. However, the 'sed instead of head' technique works even where you don't have the option of modifying the program that generates the message.

显然,这不是试图修改您的Ruby脚本。几乎可以肯定有一种方法可以在Ruby代码中实现。但是,即使您无法修改生成消息的程序,“sed而不是head”技术仍然有效。

#1


22  

head is closing the standard output stream after it has read all the data it needs. You should handle the exception and stop writing to standard output. The following code will abort the loop once standard output has been closed:

head在读取了所需的所有数据后关闭标准输出流。您应该处理异常并停止写入标准输出。一旦标准输出关闭,以下代码将中止循环:

while line = STDIN.gets
  array = CSV.parse_line(line)
  begin
    puts array[2]
  rescue Errno::EPIPE
    break
  end
end

#2


10  

The trick I use is to replace head with sed -n 1,10p.

我使用的技巧是用sed -n 1,10p替换头部。

This keeps the pipe open so ruby (or any other program that tests for broken pipes and complains) doesn't get the broken pipe and therefore doesn't complain. Choose the value you want for the number of lines.

这使得管道保持打开状态,因此ruby(或任何其他测试管道损坏和抱怨的程序)不会破坏管道,因此不会抱怨。选择所需的行数。

Clearly, this is not attempting to modify your Ruby script. There almost certainly is a way to do it in the Ruby code. However, the 'sed instead of head' technique works even where you don't have the option of modifying the program that generates the message.

显然,这不是试图修改您的Ruby脚本。几乎可以肯定有一种方法可以在Ruby代码中实现。但是,即使您无法修改生成消息的程序,“sed而不是head”技术仍然有效。