複数行があるときに別のファイルのテキストを使用してテキストファイルからプレースホルダを削除するにはどうすればよいですか?

複数行があるときに別のファイルのテキストを使用してテキストファイルからプレースホルダを削除するにはどうすればよいですか?

ファイルがあります:

  - 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\>)\'

必要な部分を選択しないと、その部分はyaml配列の次の要素(行の前)- id: 1.4.25.2に表示されます。これを行う方法とは異なる場所からインポートされたカスタムテキストを使用して、ファイル内の各項目の説明を変更する方法はわかりません。description: '<*description>'\ncontent: []- 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
$ 

関連情報