Передача переменной в AWK не работает внутри цикла

Используйте xargsдля запуска команды rm. Он будет повторно -запускать rm, каждый раз используя максимальное количество аргументов, пока не выполнит ваше первоначальное намерение *.

Словами страницы руководства:

The command line for command is built up until it reaches a system-defined limit (unless the -n and -L options are used). The specified command will be invoked as many times as necessary to use up the list of input items. In general, there will be many fewer invocations of command than there were items in the input. This will normally have significant performance benefits. Some commands can usefully be executed in parallel too; see the -P option.

4
20.04.2021, 08:27
5 ответов

При работе со структурированным текстом, таким как YAML, JSON или XML,вам действительно следует использовать синтаксический анализатор, который «понимает» структуру. Существует несколько специальных инструментов командной строки -для различных типов структурированного текста (, например. xmlstarletдля xml, jqдля json иyqдля yaml ), и большинство языков программирования/скриптов имеют библиотеки для синтаксического анализа и обработки структурированного текста.

Вот как это сделать в 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
7
28.04.2021, 22:52

вам не нужен цикл оболочки для обработки простого текста, когда у вас есть соответствующие инструменты обработки текста, -такие как ; далее мы использовали GNU awk для этого мы можем определить multu -char RS и RT, которые являются обратной -ссылкой на текущий совпадающий RS:

$ awk -v RS='(^|\n)[a-z]+:\n' 'rt ~ /^abc:\n$/ { print $NF; exit } { rt=RT }' infile
Technician

для строгой проверки того, что сообщаемое значение действительно имеет ключ "OCCUPATION" , а также передать ключ/заголовок из переменной вместо их жесткого кодирования, вы можете сделать:

$ awk -v hdr='abc' -v key='OCCUPATION' -v RS='(^|\n)[a-z]+:\n' -F'\n' \
'rt ~ ("^" hdr ":\n") { 
     for(i=1; i<=NF; i++)
         if(match($i, "^\\s*" key ":\\s*" )) { print substr($i, RSTART+RLENGTH); exit }
}
{ rt=RT }' infile
Technician
3
28.04.2021, 22:52

Использованиеyq(оболочки jqизhttps://kislyuk.github.io/yq/)для разбора YAML в командной строке (или в скрипте):

$ yq -r '.abc.OCCUPATION' file.yml
Technician

Подача abcи defв петлю оболочки:

$ for thing in abc def; do yq -r --arg node "$thing" '$node,.[$node].OCCUPATION' file.yml; done
abc
Technician
def
Engineer

или для табуляции -столбцы с разделителями:

$ for thing in abc def; do yq -r --arg node "$thing" '[$node,.[$node].OCCUPATION] | @tsv' file.yml; done
abc     Technician
def     Engineer

То есть вызовите yqс помощью --arg, за которым следует имя переменной yq, которую вы хотите установить, а затем значение, на которое вы ее устанавливаете. Затем используйте переменную в выражении yq. Это работает идентично в jq.

Без цикла оболочки и вместо этого брать значения из клавиш верхнего -уровня:

$ yq -r 'foreach keys[] as $node (.;.;[$node,.[$node].OCCUPATION]|@tsv)' file.yml
abc     Technician
def     Engineer

Существует несколько других инструментов под названием yq, которые выполняют синтаксический анализ YAML. Если вы устанавливаете yqс помощью snapв Ubuntu, вы получаете версию от человека по имени Майк Фарах. Он работает по-другому, и я обычно использую его для преобразования в JSON, а затем передаю данные вjq:

$ yq -j e file.yml | jq -r '.abc.OCCUPATION'
Technician
$ for thing in abc def; do yq -j e file.yml | jq -r --arg node "$thing" '$node,.[$node].OCCUPATION'; done
abc
Technician
def
Engineer

или для табуляции -столбцы с разделителями:

$ for thing in abc def; do yq -j e file.yml | jq -r --arg node "$thing" '[$node,.[$node].OCCUPATION] | @tsv'; done
abc     Technician
def     Engineer
6
28.04.2021, 22:52

Использование любого POSIX awk:

$ awk -v key='abc' -v fld='OCCUPATION' '
    /^[^[:space:]]/{ inKeyBlock = (index($1,key":")==1) }
    inKeyBlock && (index($1,fld":")==1) { sub(/[^:]*:[[:space:]]*/,""); print }
' file
Technician

В том маловероятном случае, если у вас нет POSIX awk или другого awk, поддерживающего классы символов, просто измените [[:space:]]на [ \t]и [^[:space:]]на [^ \t].

3
28.04.2021, 22:52
# var definitions to be used by sed
key='abc'
subkey='OCCUPATION'
s='[[:blank:]]'

# make vars plug worthy in LHS of sed
for i in \\ \[ ^ \$. \* /;do
  key=${key//"$i"/\\"$i"}
  subkey=${subkey//"$i"/\\"$i"}
done

# invoke sed with the variables
sed -ne "
  /^$key:\$/,/^[^:]*:\$/ s/^$s$s*$subkey:$s*//p
" input.yaml
Technician
0
28.04.2021, 22:52

Теги

Похожие вопросы