Подтвердить что ты не робот

Использование AWK для обработки ввода из нескольких файлов

Многие люди очень помогли, разместив сразу одно решение для AWK'а для нескольких входных файлов:

$ awk 'FNR==NR{a[$1]=$2 FS $3;next}{ print $0, a[$1]}' file2 file1

Это хорошо работает, но мне было интересно, может ли кто-нибудь объяснить мне почему? Я нахожу синтаксис AWK немного жестким, чтобы получить зависание, и надеялся, что кто-то не прочь сломать фрагмент кода для меня.

4b9b3361

Ответ 1

awk 'FNR==NR{a[$1]=$2 FS $3;next}

здесь мы обрабатываем первый вход (файл2). скажем, FS - это пространство, мы строим массив (a) вверх, index - столбец1, значение column2 " " column3 означает FNR==NR and next, эта часть кодов работает только для file2. вы могли бы man gawk проверить, что такое NR и FNR

{ print $0, a[$1]}' file2 file1

Когда NR != FNR время для обработки второго ввода, file1. здесь мы печатаем строку file1 и берём column1 в качестве индекса, узнаем значение в массиве (a) print. в другом слове file1 и file2 объединяются в один столбец1 в обоих файлах.

для NR и FNR, в ближайшее время

1st input has 5 lines
2nd input has 10 lines,

NR would be 1,2,3...15
FNR would be 1...5 then 1...10

вы видите трюк проверки FNR==NR.

Ответ 2

Я нашел этот вопрос/ответ в Google и, похоже, ссылается на очень конкретный набор данных, найденный в другом вопросе (Как объединить два файла с помощью AWK?). Ниже следует ответ, который я искал (и, как я думаю, большинство людей будет), т.е. Просто объединить каждую строку из двух разных файлов с помощью AWK. Хотя вы, вероятно, могли бы использовать некоторые утилиты UNIX, такие как join или вставить, AWK, очевидно, намного более гибкая и мощная, если ваш желаемый результат отличается, используя if или изменить OFS (что может быть труднее сделать в зависимости от утилиты, см. ниже), например, изменение вывода в гораздо более выразительном виде (важное соображение для сценариев оболочки.)

Для простой поэтапной конкатенации:

awk 'FNR==NR { a[FNR""] = $0; next } { print a[FNR""], $0 }' file1 file2

Это эмулирует функцию массива с числовой индексацией (AWK имеет только ассоциативные массивы), используя неявное преобразование типа. Это относительно выразительно и легко понять.

Используя два файла с именем test1 и test2 со следующими строками:

test1:

line one
line two
line three

test2:

line four
line five
line six

Получаю этот результат:

line one line four
line two line five
line three line six

В зависимости от того, как вы хотите объединить значения между столбцами на выходе, вы можете выбрать соответствующий разделитель полей вывода. Здесь пример с эллипсами (...), разделяющими столбцы:

awk 'BEGIN { OFS="..."} FNR==NR { a[(FNR"")] = $0; next } { print a[(FNR"")], $0 }' test1 test2

Удовлетворение этого результата:

line one...line four
line two...line five
line three...line six

Надеюсь, по крайней мере, это вдохновляет всех вас на то, чтобы воспользоваться мощью AWK!

Ответ 3

Некоторое время назад я наткнулся на очень хорошее решение для обработки нескольких файлов одновременно. Способ заключается в том, чтобы сохранить в памяти файлы в массивах AWK, используя метод:

FILENAME==ARGV[1] {  file2array[FNR] = $0 ; next }
FILENAME==ARGV[2] {  file1array[FNR] = $0 ; next }

Для обработки данных после записи лучше сохранить количество строк, поэтому:

FILENAME==ARGV[1] {  file2array[FNR] = $0 ; f2rows = FNR ; next }
FILENAME==ARGV[2] {  file1array[FNR] = $0 ; f1rows = FNR ; next }

f2rows и f1rows будут держать позицию последнего ряда.

В нем больше кода, но если вы хотите более сложную обработку данных, я думаю, что это лучший подход. Кроме того, предыдущие подходы обрабатывали входные данные последовательно, поэтому, если вам нужно было выполнить некоторые вычисления, которые зависели от данных из обоих файлов одновременно, вы не смогли бы сделать это, и с этим подходом вы можете делать все с обоими файлами.

Ответ 4

Tpdsantos, это отличный вклад здесь. Спасибо за публикацию.