Я новичок в awk, я пытаюсь получить значение из файла, используя ключ в другом файле.

Файл значений:

1   39485063845911  RANDOMTEXT    RANDOMNUMBERS
1   39485063845912  RANDOMTEXT    RANDOMNUMBERS
1   39485063845913  RANDOMTEXT    RANDOMNUMBERS
1   39485063845914  RANDOMTEXT    RANDOMNUMBERS

Ключевой файл:

1   39485063845911  RANDOMTEXT
1   39485063845912  RANDOMTEXT

Я пытался адаптировать предыдущую версию awk, но не смог.

awk 'BEGIN {FIELDWIDTHS="7 14 3 28 3 25"} NR==FNR {data["0"$14];next} NR!=FNR {FIELDWIDTHS="7 14 3 28"} {if(!($14) in data) {print $0}}' file

Числа внутри FIELDWIDTHS 'представляют' ширину столбца (оба являются позиционными файлами), а $14 - это ширина ключевого столбца.

Таким образом, выходной файл приведенного выше примера должен быть:

1   39485063845911  RANDOMTEXT    RANDOMNUMBERS
1   39485063845912  RANDOMTEXT    RANDOMNUMBERS
awk
1
Icaro Americo 17 Авг 2021 в 15:35

3 ответа

Лучший ответ

Ваш код с разрывами строк для ясности:

awk '
    BEGIN {FIELDWIDTHS="7 14 3 28 3 25"}
    NR==FNR {data["0"$14];next}
    NR!=FNR {FIELDWIDTHS="7 14 3 28"}
   {if(!($14) in data) {print $0}}
' file
  1. Вы устанавливаете FIELDWIDTHS в каждой строке второго (или более позднего) файла, а не только один раз - это неэффективно
  2. Вы читаете только один файл, поэтому ничего не будет напечатано
  3. Вы, кажется, думаете, что $14 каким-то образом относится к полю длиной 14
  4. Похоже, вы отказались от теста, который использовали бы, если хотите распечатать записи из файла значений, которые соответствуют записям в ключевом файле (вам следует делать if (x in y), а не if (!(x in y)))

Возможно, вам понадобится что-то вроде:

gawk '
  FNR==1 { FIELDWIDTHS = NR==FNR ? "7 14 3 28" : "7 14 3 28 3 25" }
  NR==FNR { keys[$2]++; next }
  $2 in keys  { print }
' keyfile valuefile

Этот:

  • устанавливает FIELDWIDTHS только один раз для каждого входного файла
  • использует как файл ключей, так и файл значений
  • относится к полю 2 ($2), которое, по-видимому, является тем, которое вы хотите использовать в качестве ключевого
  • тесты на наличие, а не на отсутствие
  • явно использует gawk вместо awk, чтобы избежать неприятных сюрпризов (если используется версия, не поддерживающая POSIX FIELDWIDTHS)
3
jhnc 17 Авг 2021 в 20:24

Я знаю, что вы говорите о FIELDWIDTHS и позициях персонажей в своем вопросе, но вы также сказали: «Я новичок в awk», и в вашем скрипте есть несколько ошибок новичков, поэтому вы можете не полностью осознавать, как его использовать, и учитывая пример, который вы предоставили, все, что вам действительно нужно:

$ awk 'NR==FNR{a[$2]; next} $2 in a' key values
1   39485063845911  RANDOMTEXT    RANDOMNUMBERS
1   39485063845912  RANDOMTEXT    RANDOMNUMBERS

Если это не все, что вам нужно, отредактируйте свой вопрос, чтобы предоставить более реалистичный образец ввода / вывода, включая случаи, когда вышеперечисленное не работает.

2
Ed Morton 17 Авг 2021 в 16:40

Или добавив третью возможность, это может быть так же просто, как grep -f. Например:

grep -f keyfile valuefile

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

С использованием строк из ключевого файла для сопоставления в файле значений.

Пример использования / вывода

Для вашего примера выше:

$ grep -f keyfile valuefile
1   39485063845911  RANDOMTEXT    RANDOMNUMBERS
1   39485063845912  RANDOMTEXT    RANDOMNUMBERS
1
David C. Rankin 17 Авг 2021 в 21:18