2015-05-23 64 views
5

有沒有辦法在YAML中替換字符串。例如,我想定義sub一次,並在整個YAML文件中使用它。是否可以在YAML中進行字符串替換?

sub: ['a', 'b', 'c'] 
command: 
    params: 
     cmd1: 
      type: string 
      enum : # Get the list defined in 'sub' 
      description: Exclude commands from the test list. 
     cmd2: 
      type: string 
      enum: # Get the list defined in 'sub' 
+0

看一看:http://en.wikipedia.org/wiki/YAML#References – smj

+0

我改變了你YAML代碼,因爲它在序列「sub」中的'b'之後錯過了一個單引號。請注意,這些引用是多餘的,在我的回答中使用輸入時,我將它們排除在外。 – Anthon

回答

7

在YAML中不能真正替換字符串值,如用另一個子字符串'替換某個字符串的子字符串'。然而YAML確實有可能標記的節點(在你的情況下,列表[「A」,「B」,「C」]與anchor和再利用,作爲一個alias node

錨採取的形式&some_id和是在節點和別名之前插入的節點由*some_id(而不是節點)指定

這與字符串級別的替換不同,因爲在分析YAML文件時可以保留引用。在Python中針對集合類型上的任何錨加載YAML的情況(即當在標量上使用錨時,即而不是):

import sys 
import ruamel.yaml as yaml 

yaml_str = """\ 
sub: &sub0 [a, b, c] 
command: 
    params: 
     cmd1: 
      type: string 
      # Get the list defined in 'sub' 
      enum : *sub0 
      description: Exclude commands from the test list. 
     cmd2: 
      type: string 
      # Get the list defined in 'sub' 
      enum: *sub0 
""" 

data1 = yaml.load(yaml_str, Loader=yaml.RoundTripLoader) 

# the loaded elements point to the same list 
assert data1['sub'] is data1['command']['params']['cmd1']['enum'] 

# change in cmd2 
data1['command']['params']['cmd2']['enum'][3] = 'X' 


yaml.dump(data1, sys.stdout, Dumper=yaml.RoundTripDumper, indent=4) 

這將輸出:

sub: &sub0 [a, X, c] 
command: 
    params: 
     cmd1: 
      type: string 
      # Get the list defined in 'sub' 
      enum: *sub0 
      description: Exclude commands from the test list. 
     cmd2: 
      type: string 
      # Get the list defined in 'sub' 
      enum: *sub0 

請注意,原來的錨名在ruamel.yamlpreserved²。

如果你不想在你的輸出的錨和別名,你可以覆蓋RoundTripRepresenter子類的RoundTripDumperignore_aliases方法(該方法有兩個參數,但使用lambda *args: ....你不必知道這個問題):

dumper = yaml.RoundTripDumper 
dumper.ignore_aliases = lambda *args : True 
yaml.dump(data1, sys.stdout, Dumper=dumper, indent=4) 

其中給出:

sub: [a, X, c] 
command: 
    params: 
     cmd1: 
      type: string 
      # Get the list defined in 'sub' 
      enum: [a, X, c] 
      description: Exclude commands from the test list. 
     cmd2: 
      type: string 
      # Get the list defined in 'sub' 
      enum: [a, X, c] 

這一招可以用在YAML文件讀取,如果你做了字符串替換,通過重新閱讀而忽略了你傾倒的材料別名:

data2 = yaml.load(yaml.dump(yaml.load(yaml_str, Loader=yaml.RoundTripLoader), 
        Dumper=dumper, indent=4), Loader=yaml.RoundTripLoader) 

# these are lists with the same value 
assert data2['sub'] == data2['command']['params']['cmd1']['enum'] 
# but the loaded elements do not point to the same list 
assert data2['sub'] is not data2['command']['params']['cmd1']['enum'] 

data2['command']['params']['cmd2']['enum'][5] = 'X' 

yaml.dump(data2, sys.stdout, Dumper=yaml.RoundTripDumper, indent=4) 

現在只有一個'b'改爲'X'

sub: [a, b, c] 
command: 
    params: 
     cmd1: 
      type: string 
      # Get the list defined in 'sub' 
      enum: [a, b, c] 
      description: Exclude commands from the test list. 
     cmd2: 
      type: string 
      # Get the list defined in 'sub' 
      enum: [a, X, c] 

如圖所示上方集合類型使用錨/別名時,這僅僅是必須的,而不是當你使用它的標。


¹由於YAML可以創建對象,然而,有可能影響 如果創建這些對象的解析器。 This answer描述瞭如何做到這一點。
²保留名原是不可用,但在ruamel.yaml的更新被實施

相關問題