YAMLファイルを読み取り、特定の値を出力するawk文があります。値リストからキー値を読み取り、そのキーをawkに渡すループでこのawkを繰り返す必要があります。
YAMLファイルの構造は次のとおりです。
abc:
NAME: Bob
OCCUPATION: Technician
def:
NAME: Jane
OCCUPATION: Engineer
abc
OCCUPATION
キー値を取得したいと仮定し、TECHNICIAN
インターネット検索を介して私が欲しいものを提供するawkステートメントを設定しました。
> awk 'BEGIN{OFS=""} /^[^ ]/{ f=/^abc:/; next } f{ if (sub(/:$/,"")) abc=$2; else print abc,$1 $2}' test.yml| grep "OCCUPATION:" | cut -d':' -f2
Technician
しかし、このループを使用すると、-vオプションをawkに渡しても結果が出ないようです。
items="abc,def"
for item in $(echo $items | sed "s/,/ /g");
do
echo $item;
awk -v name="$item" 'BEGIN{OFS=""} /^[^ ]/{ f=/^\name:/; next } f{ if (sub(/:$/,"")) name=$2; else print name,$1 $2}' test.yml| grep "OCCUPATION:" | cut -d':' -f2;
done
私が設定したデバッグエコーのみが表示されます。
abc
def
私はどこで間違っていますか?変数がawkで正しく解釈されるべきだと思いますか?
編集:Steeldriversのコメントに基づいて入力内容を一部変更しました。
items="abc,def"
for item in $(echo $items | sed "s/,/ /g");
do
echo $item;
awk -v name="$item" 'BEGIN{OFS=""} /^[^ ]/{ f=name; next } f{ if (sub(/:$/,"")) name=$2; else print name,$1 $2}' test.yml| grep "OCCUPATION:" | cut -d':' -f2;
done
ただし、OCCUPATION
すべての値が印刷されます。
abc
Technician
Engineer
def
Technician
Engineer
演算子を試してみましたが、~
エラーが発生して正しく使用されていないため、値を直接解析することにしましたが、重複が生成されます。
ベストアンサー1
YAML、JSON、XMLなどの構造化テキストで作業するときは、構造を「理解する」パーサーを使用する必要があります。さまざまな種類の構造化テキスト(例:xmlstarlet
xml、jq
json、yqyamlの場合)ほとんどのプログラミング/スクリプト言語には、構造化テキストを解析して処理するためのライブラリがあります。
PerlコアYAMLモジュールを使用してPerlでこれを行う方法は次のとおりです。
(YAMLモジュールがコアモジュール展開の標準部分として含まれている場合は、perl> = 5.14バージョンが必要です。Perl 5.14は2013年にリリースされました。以前のバージョンのPerlの場合を使用してYAMLをインストールできますcpan
。
#!/usr/bin/perl
use strict;
use YAML qw(LoadFile);
my $file = shift; # first arg is the input filename
my $data = LoadFile($file); # load the yaml data into a hashref variable
# loop over the remaining args (i.e. the keys)
foreach my $item (@ARGV) {
print "$item\n";
print $$data{$item}{'OCCUPATION'}, "\n";
}
たとえば、別の名前で保存しyaml.pl
て実行可能にしますchmod +x yaml.pl
。
yamlデータがというファイルに保存されている場合は、input.yaml
次のように実行できます。
$ ./yaml.pl input.yaml abc def
abc
Technician
def
Engineer
awkやsedのように、これは理解しにくい1行に圧縮できます。
$ perl -MYAML=LoadFile -E '$data=LoadFile(shift);foreach (@ARGV) {say $_;say $$data{$_}{"OCCUPATION"}}' input.yaml abc def
abc
Technician
def
Engineer
Perlは自動的にパラメータを分割することもできます。たとえば、foreach
ループを次のように変更すると:
foreach my $item (split /\s*,\s*/,join(",",@ARGV)) {
次のように実行できます。
$ ./yaml.pl input.yaml abc def
または
$ ./yaml.pl input.yaml "abc,def"
または任意の組み合わせ(ghiキーとjklキーが使用されていると仮定):
$ ./yaml.pl input.yaml "abc,def" ghi jkl