объяснение массива awk?

Изman ssh-keygen:

SYNOPSIS
     ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
                [-N new_passphrase] [-C comment] [-f output_keyfile]

Вы можете сделать что-то подобное:

ssh-keygen -t rsa -N "" -f /wherever/you/want/id_rsa

Если вы хотите отключить сообщения пользователя ssh-keygen, добавьте параметр -qв командную строку.

2
10.08.2020, 15:16
2 ответа

Целью этого скрипта является замена значений в третьем столбце второго файла(filex)соответствующими значениями, хранящимися во втором столбце первого файла(filez).

NR— номер текущей строки относительно первой строки первого обрабатываемого файла. Это "глобальный" счетчик строк. FNR— номер текущей строки относительно начала обрабатываемого в данный момент файла.
NR==FNR— это условие, которое оценивается как истинное только для первого файла. Соответствующее действие({a[$1]=$2;next})вводит весь первый файл, строка за строкой, в словарь a— ассоциативный массив, целью которого является поиск значений второго столбца первого файла на основе соответствующих значений в первом столбце. nextзаставляет awkпропустить оставшиеся условия и перезапустить цикл, читая следующую строку.

$3 in a && $3 = a[$3]— это состояние с потенциальным побочным эффектом (присваивания$3). Он оценивается только для второго файла (, когда NR==FNRимеет значение false; помните, что когда NR==FNRбыло истинным, $3 in a && $3 = a[$3]пропускалось ). Для каждой строки, если значение третьего поля найдено (как индекс )в словаре a, оно заменяется соответствующим значением из словаря. Затем, если $3 = a[$3]оценивается как истинное, печатается строка (, потому что в программах AWK, которые в основном состоят из пар условий (или "шаблонов" )-действий, либо условие, либо действие могут быть опущены., а пропущенное действие эквивалентноprint).

Предполагая, что это сокращеноfilez:

111,111
112,114

иfilex:

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn

то, что происходит шаг за шагом,:

  1. читается первая строка filez; NR==FNRоценивается как 1==1, истина; таким образом, {a[$1]=$2;next}выполняется; a[111]устанавливается на 111; nextозначает, что остальная часть скрипта($3 in a && $3 = a[$3])пропущена для этой строки (конкретно, $3пока не используется ); ничего не печатается, потому что в выполняемом действии нет команды печати;

  2. читается вторая и последняя строка filez; NR==FNRоценивается как 2==2, истина; {a[$1]=$2;next}выполняется; a[112]устанавливается на 114; $3 in a && $3 = a[$3]снова пропускается из-за next; и снова ничего не печатается;

  3. читается первая строка filex; NR==FNRоценивается как 3==1, ложь; таким образом, {a[$1]=$2;next}является , а не выполненным; следующее оцениваемое условие:$3равно 111и является значением индекса a, следовательно, $3 in aистинно и $3 = a[$3]оценивается; это вызывает назначение a[111], то есть 111, на $3; поскольку 111не является 0и не является пустой строкой, присваивание условия -также оценивается как истинное, и печатается текущая строка;

    A,bb,111,xxx,nnn
    
  4. читается вторая и последняя строка filex; NR==FNRоценивается как 4==2, ложь; таким образом, {a[$1]=$2;next}является , а не выполненным; следующее оцениваемое условие:$3равно 112и является значением индекса a, следовательно, $3 in aистинно и $3 = a[$3]оценивается; это вызывает назначение a[112], то есть 114, на $3; поскольку 114не является 0и не является пустой строкой, присваивание условия -также оценивается как истинное, и печатается текущая строка.

    A,cc,114,yyy,nnn
    
6
18.03.2021, 23:15
  • BEGIN{OFS=FS=","}устанавливает разделители полей ввода и вывода на ,.
  • NR==FNRверно только для первого файла. Итак, для первого файла :
    • a[$1]=$2поместите $1в качестве индекса и $2в качестве значения в массиве a.
    • nextпропустить оставшуюся часть скрипта для этой строки.

Опять же:nextозначает, что оставшаяся часть скрипта выполняется только для второго файла(и третьего, четвертого,... файлов, если они присутствовали ).

  • $3 in a && $3 = a[$3]Если третье поле является ключом массива a, замените третье поле на a[$3]. Сейчас,так как это не в среде действия (, т.е. не внутри {}), значит, если оба условия верны, текущая запись должна быть напечатана. В противном случае ничего не нужно делать.

Обычно , поскольку условие справа является присваиванием, оно будет иметь значение true, если левая сторона верная. Однако присваивание оценивается как ложное, если оно присваивает пустая строка или число 0. Это может быть задумано, но обычно это крайний -случай что программист не заметил. Чтобы увидеть это, попробуйте код awk с

filez:

111,111
112,114
113,113
000,000

filex:

A,bb,111,xxx,nnn
A,cc,112,yyy,nnn
A,dd,113,zzz,ppp
A,ee,000,uuu,aaa

Обратите внимание, что для последней строки, хотя $3 in aверно, $3 = a[$3]присваивает 0 и, таким образом, строка не печатается!

$ awk 'BEGIN{OFS=FS=","}NR==FNR{a[$1]=$2;next}$3 in a && $3 = a[$3]' filez filex
A,bb,111,xxx,nnn
A,cc,114,yyy,nnn
A,dd,113,zzz,ppp

По запросу ОП о разъяснении:

Помните :Массив заполняетсяa[$1]=$2в первом файле , filez.
$3 = a[$3]выполняется для второго файла , filex.
Например, :Во второй строке filez,a[$1]=$2-> a[112] = 114. Во второй строке filex,$3 = a[$3]-> 112=a[112]=114.

4
18.03.2021, 23:15

Теги

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