Bash I / O重定向可以在Ruby脚本中工作吗?

时间:2013-02-08 04:25:12

标签: ruby bash shell

在Bash中,我想比较两个不同CSV的字段(file1的字段2和file2的字段3):

diff <(cut -d, -f2 file1) <(cut -d, -f3 file2)

我试图在Ruby中更普遍地实现它:

def identical_files?(file1, field1, file2, field2)                                                                                                              
  %x{diff <(cut -d, -f#{field1} #{file1}) <(cut -d, -f#{field2} #{file2})}.blank?                                   
end

打印%x{}块的输出,我看到sh: Syntax error: "(" unexpected。在Ruby中运行shell命令时,I / O重定向是否不起作用?这是因为它只受bash支持但不支持sh?

3 个答案:

答案 0 :(得分:4)

它不起作用,因为正如你所得到的错误所表明的那样,Ruby会抨击sh,而不是Bash。当然,sh不支持该语法。

您可以明确地调用Bash:

`bash -c 'cat <(echo foo)'`  #=> "foo"

答案 1 :(得分:0)

  

这是因为它只受bash的支持而不是sh?

sh不支持进程替换,即使sh实际上是bash(兼容性)。

答案 2 :(得分:0)

请勿尝试使用像cut这样简单的内容来处理CSV文件中的字段。 CSV文件可以在字段内部嵌入逗号,这将欺骗,导致您的代码做错事。

相反,使用专门设计用于处理CSV文件的内容,例如Ruby的CSV类。像这个未经测试的代码会让你开始:

require 'csv'

csv_file1 = CSV.open('file1')
csv_file2 = CSV.open('file2')

until (csv_file1.eof? || csv_file2.eof?) do
  row1 = csv_file1.shift
  row2 = csv_file2.shift

  # do something to diff the fields
  puts "#{ csv_file1.lineno }: #{ row1[1] } == #{ row2[2] } --> #{ row1[1] == row2[2] }"
end

[
  [csv_file1, 'file1'],
  [csv_file2, 'file2']
].each do |f, fn|
  puts "Hit EOF for #{ fn }" if f.eof?
  f.close
end