Bash

將變數傳遞給 AWK 在循環中不起作用

  • April 23, 2021

我有這個讀取 YAML 文件並輸出特定值的 awk 語句。我需要在一個循環中循環這個 awk,我從值列表中讀取一個鍵值並將該鍵傳遞給 awk。

YAML 文件具有以下結構:

abc:
 NAME: Bob
 OCCUPATION: Technician
def:
 NAME: Jane
 OCCUPATION: Engineer

假設我想獲得 的鍵值abc OCCUPATIONTECHNICIAN通過Google搜尋我設法構造了一個 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

我嘗試使用該~運算符,但我認為我沒有正確使用它,因為它給了我錯誤,所以我決定直接解析該值,但這會給出重複項:/

在處理 YAML、JSON 或 XML 等結構化文本時,您確實應該使用“理解”結構的解析器。有幾種特定的命令行工具可用於各種結構化文本(例如xmlstarlet用於 xml、jq用於 json 和用於 yaml 的**yq**),並且大多數程式/腳本語言都有用於解析和處理結構化文本的庫。

以下是使用 perl 核心 YAML 模組在 perl 中執行此操作的方法:

(這需要 perl >= 5.14 的版本,此時 YAML 模組作為核心模組分發的標準部分包含在內。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 一樣,這也可以濃縮成一個高深莫測的單行:

$ 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

引用自:https://unix.stackexchange.com/questions/645719