我有一个文件:
- id: 1.4.25.2
name: 'Configuring a VNC Server'
permalink: '/rhcsa/managing-network-services/configuring-vnc-access/configuring-a-vnc-server'
description: '<*description>'
content: []
- id: 1.4.25.3
name: 'Connecting to a VNC Server'
permalink: '/rhcsa/managing-network-services/configuring-vnc-access/connecting-to-a-vnc-server'
description: '<*description>'
content: []
我必须<*description>
用一些文本替换每个内容。显然,我想到使用正则表达式。显然(根据本网站上的某些答案),sed
没有用于替换的非贪婪修饰符。因此,我尝试使用 perl:
(.*id: 1\.4\.25\.2(?:\n|.)*)\'(\<\*description\>)\'
不选择所需的部分,该部分将来自- id: 1.4.25.2
直到description: '<*description>'\ncontent: []
yaml 数组中下一个元素之前,即 line 之前- id: 1.4.25.3
。我想不出一种方法来做到这一点,以及如何使用从其他地方提取的自定义文本来更改文件中每个条目的描述!
答案1
使用 YAML 模块;递归遍历数据结构,并将此处的任何匹配元素替换为标准输入上读入的行。
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use YAML::Tiny;
my $yaml =
YAML::Tiny->read( $ARGV[0] // die "Usage: $0 yaml-file [out-file]\n" );
mangle_description( $yaml->[0] );
$yaml->write( $ARGV[1] // "$ARGV[0].out" );
sub mangle_description {
my $what = shift;
my $type = ref $what;
if ( $type eq 'HASH' ) {
for my $key ( keys %$what ) {
if ( $key eq 'description'
and $what->{$key} eq '<*description>' ) {
$what->{$key} = set_description();
}
mangle_description( $what->{$key} ) if ref $what->{$key};
}
} elsif ( $type eq 'ARRAY' ) {
for my $entry (@$what) {
mangle_description($entry);
}
} else {
warn Dumper $what;
die "unknown type in YAML ??\n";
}
}
sub set_description {
my $next = readline *STDIN;
chomp $next;
return $next;
}
上面的内容保存为parser
并使用有效的 YAML 在input
:
$ yes | perl parser input
$ grep description input.out
description: y
description: y
$