2013-02-08 47 views
1

在bash,我想比較的2周不同的CSV(文件1場2和file2場3)字段:Bash I/O重定向可以在Ruby腳本中工作嗎?

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?

回答

4

它不起作用,因爲正如你所得到的錯誤表明,Ruby將彈出sh而不是Bash。當然,sh不支持這種語法。

您可以改爲調用猛砸明確:

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

謝謝。真的很感激它! – gwintrob

0

這是因爲它只支持bash而不是sh?

是。

sh不支持進程替換,即使sh實際上是bash(爲了兼容性)。

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