2017-05-24 44 views
0

我有有一個列測試一個CSV文件,身份證件和值替換CSV字符串:使用正則表達式使用Ruby

"abc is 123 test", 1 

"abc is 123 test", 2 

"abc is 123 test", 3 

"abc is 123 test", 4 

"abc is 123 test", 5 

我想"abc is 567 test"更換"abc is 123 test"

注:值123567是動態值,與每一個新的CSV 123得到改變,但串"abc is <value> test"始終保持不變。

代碼我想:

folder_path = "/home/test/files/" 
f1 = folder_path + "abc.csv" 
string_replace = "abc is 567 test" 

file = IO.read(/home/test/files/abc.csv") 
file_final = expected_file.gsub!("abc is".*, string_replace) 
File.open(f1, 'w') { |f| f.write(file_final) } 

我收到錯誤:

"ArgumentError: wrong number of arguments calling * (0 for 1)

誰能幫助?

+0

它可以是多於3位數字或不到3個數字爲好。 – rubyUser

+0

「abc是123測試」中的數字總是三位數? –

+0

使用'read'和正則表達式是一個壞主意,除非你總是知道該文件很容易裝進內存。與使用逐行IO相比,超過2MB的任何內容都會使您的代碼變慢。 https://stackoverflow.com/questions/25189262/ –

回答

1

雖然技術上文件是CSV文件,但我們可以將CSV文件視爲文本,因爲這就是它們。當他們很簡單時,這可以讓他們更容易。

我開始:

File.open('csv.new', 'w') do |fo| 
    DATA.each_line do |li| 
    fo.puts li.sub('123', '456') 
    end 
end 

__END__ 
"abc is 123 test", 1 
"abc is 123 test", 2 
"abc is 123 test", 3 
"abc is 123 test", 4 
"abc is 123 test", 5 

運行它會生成一個名爲 「csv.new」 文件,其中包含:

"abc is 456 test", 1 
"abc is 456 test", 2 
"abc is 456 test", 3 
"abc is 456 test", 4 
"abc is 456 test", 5 

相反的:

DATA.each_line do |li| 

你」 d要使用以下方式打開原始文件:

File.foreach("/home/test/files/abc.csv") do |li| 

DATA__END__是訪問存儲在一個Ruby腳本的末尾採樣數據的一種方式。)

'123'容易出現假陽性命中,並且將改變的子串:

''.sub('123', '456') # => "0456456" 

爲了反擊這一點,如果有任何機會的子串匹配,你想使用更智能的搜索字符串;我會使用一個正則表達式:

''.sub(/\b123\b/, '456') # => "" 

現在檢查,看看是否有周圍123一個字邊界:

'0 123 456'.sub(/\b123\b/, '456') # => "0 456 456" 

由於「123」可能會改變,它會是有意義的給它分配到恆定則替換該入模式:

TARGET_STR = '123' 

''.sub(/\b#{TARGET_STR}\b/, '456') # => "" 
'0 123 456'.sub(/\b#{TARGET_STR}\b/, '456') # => "0 456 456" 

因爲我使用的塊與openforeach,紅寶石自動將一旦塊結束,關閉文件,導致更簡潔的代碼,並更好地管理文件句柄。

您的代碼:

file = IO.read(/home/test/files/abc.csv") 
file_final = expected_file.gsub!("abc is".*, string_replace) 
File.open(f1, 'w') { |f| f.write(file_final) } 

...是一個...混亂。

  • read對於你知道文件總是小於1MB的文件來說很棒。如果你不知道,特別是如果你在生產環境中工作,其中的文件可以順利進入國標範圍內,使用行由行IO速度更快,因爲它迴避可擴展性問題更安全。有關更多信息,請參閱「Why is "slurping" a file not a good practice?」。
  • 我們不知道什麼是​​,而是因爲它是未定義因此Ruby會造反,因爲你使用的gsub!方法在零值,它會導致錯誤。
  • 如果​​是一個字符串,expected_file.gsub!會變異​​,但將結果分配給file_final會浪費CPU。相反重用​​,或者更好的,使用方法:

    file_final = expected_file.gsub(
    
  • "abc is".*是一個無效的參數。可能"abc is.*"就會更接近,但它似乎你達到了一個正則表達式/abc is.*/,但就沒有必要改變字符串,/123/'123'就足夠了。

  • gsub在這裏也是過分的,因爲您只需要一個替換,所以sub會更快。
  • 技術上,

    File.open(f1, 'w') { |f| f.write(file_final) } 
    

    的工作,但它更容易寫成

    File.write(f1, file_final) 
    

您可以將代碼簡化爲:

File.write(
    'file.csv.new', 
    File.read('file.csv').gsub(/\b123\b/, '456') 
) 
其中,出乖張的,可以寫成

File.write('file.csv.new', File.read('file.csv').gsub(/\b123\b/, '456')) 

有會是在速度上沒有改善,反而它會降低可讀性。