2016-11-17 36 views
1

我正在使用to_yaml將數組寫入Ruby中的YAML文件。在寫入文件後,我需要在YAML指令行(---)或三條破折號下添加另一行或單詞。如何使用Ruby將行注入到YAML文件

有沒有辦法在我寫YAML文件後做到這一點?或者一般來說這樣做是否有更好的方法?

我從一個YAML文件讀取寫入到另一個:

items = YAML::load(File.open(yaml_file) 

items.each do |key, value| 
    item = items["#{key}"] 
    f = File.open("/tmp/blah.yaml", 'w') 
    f.puts item.to_yaml 
    f.close 
end 

後它寫入YAML文件正確,我意識到,我需要添加YAML指令線下的另一條線。我需要添加三條短線下方的詞類(---):

--- 
- blah::words 
- blah::words 
+0

不確定我完全理解你想要做什麼,但'#to_yaml'返回一個字符串,所以你應該可以在事實之後使用任何字符串方法。 – moveson

+0

更新了我的帖子,希望能夠清除任何混淆。感謝您的迴應! –

+4

看起來你正在讀取YAML文件,但嘗試逐行寫入另一個YAML文件。手動逐行寫入YAML非常容易出錯(我沒有看到這樣做的合理理由)。相反,在內存中構建數據結構並一次性寫入YAML文件。 – spickermann

回答

0

YAML是對象的序列化版本,可以是散列或數組。由於序列化器的工作方式,根據規範,我們不能在任何舊的地方粘貼輸出,它必須在語法上是正確的。而且,最簡單的方法是讓YAML解析器和序列化程序爲您處理它。

例如:

require 'yaml' 

foo = {'a' => 1} 
puts foo.to_yaml 

,其輸出:

--- 
a: 1 

並且是YAML格式的簡單散列。

我們可以做到這表明往返是正確的:

bar = foo.to_yaml 
YAML.load(bar) # => {"a"=>1} 

更復雜的對象展示瞭如何變得棘手:

foo = {'a' => [1,2], 'b' => {'c' => [3, 4]}} 
puts foo.to_yaml 

導致:

--- 
a: 
- 1 
- 2 
b: 
    c: 
    - 3 
    - 4 

還有其他方法可以指定一個數組,但這是序列化程序的默認值。如果你添加了一行,取決於你添加的內容,它必須在a:b:之前,這會在編寫代碼時很痛苦,或者在- 4之後附加到文件上。

相反,我們可以加載和解析文件,然後重新生成所需的對象,然後重寫YAML文件,知道語法是正確的。

在下面的代碼,想象bar是使用的結果YAML的load_file,其讀取並解析YAML文件,而不是我的使用load只解析序列化對象:

require 'yaml' 

bar = YAML.load("---\na: [1]\n") # => {"a"=>[1]} 

我可以修改bar

bar['b'] = {'c' => [2,3,4]} 

下面是修改的對象:

bar # => {"a"=>[1], "b"=>{"c"=>[2, 3, 4]}} 

,並使用to_yaml將寫入正確的YAML序列化:

bar.to_yaml # => "---\na:\n- 1\nb:\n c:\n - 2\n - 3\n - 4\n" 

如果是這樣:

File.write('foo.yaml', bar.to_yaml) 

你已經完成了,沒有任何真正的麻煩的變化。

我不推薦覆蓋文件,而是通過寫入新文件,重新命名舊文件,將新文件重命名爲舊文件名,然後刪除重命名的舊文件,推薦遵循安全文件覆蓋實踐。這有助於確保在代碼或機器死亡導致您丟失所有數據時文件不會被破壞。

0

如果你想在文件的最後添加的東西,然後就寫這之間:

f.puts item.to_yaml 

f.close 

但是,您應該考慮將key(因爲它是唯一的)作爲您編寫的YAML文件的文件名的一部分。正如你的/tmp/blah.yaml是爲第一個密鑰寫的,並且覆蓋了在each循環中處理的每個下一個密鑰,這可能不是你想要的。

相關問題