有没有办法在YAML中替换字符串。例如,我想定义- (void)timerFired:(NSTimer *)timer {
seconds++;
[self someCommonMethod:timer];
condition++;
}
- (void)someCommonMethod:(id)param {
if (condition == 0)
[self drawFoo];
if (condition == 1)
[self drawBoo];
if (condition == 2)
[self drawYoo];
}
- (IBAction)reStart:(id)sender {
condition = 0;
[self someCommonMethod:someParamForConditions];
}
一次并在整个YAML文件中使用它。
sub
答案 0 :(得分:12)
你无法在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.yaml。
如果您不想在输出中使用锚点和别名,则可以覆盖ignore_aliases
RoundTripRepresenter
子类中的RoundTripDumper
方法(该方法需要两个参数,但使用{ {1}}你不必知道这一点):
lambda *args: ....
给出了:
dumper = yaml.RoundTripDumper
dumper.ignore_aliases = lambda *args : True
yaml.dump(data1, sys.stdout, Dumper=dumper, indent=4)
这个技巧可以用来读取YAML文件,好像你已经完成了字符串替换,重新读取你转储的材料而忽略了别名:
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]
现在只有一个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'
如上所述,只有在集合类型上使用锚点/别名时才需要这样做,而不是在标量上使用它时。
¹由于YAML可以创建对象,因此可能会产生影响
解析器是否创建了这些对象。 This answer描述了如何做到这一点。
²保留名称最初不可用,但是在ruamel.yaml的更新中实现