Awk выдает ошибку, потому что переменная "c" установлена равной пустой переменной. $maximum еще не установлен.
Вы должны сделать:
awk -v c=`cat maximum` '{print $1/c}' CVBR1_hist > CVBR1_norm
Вот где ваша команда потерпела неудачу.
Лучший способ: не обращаться к временному файлу, а хранить максимальное значение в переменной, как в ответе Кусалананды.
Теперь, когда я увидел ваше исследование, я даю вам свое решение:
awk '{ z[$1]=z[$1]$2 } END { for (i in z) print i, z[i] }' file1 file2
вывод:
002 BD
003 CD
004 D
005 E
006 F
001 A
Если вы хотите выполнить числовую сортировку значений первого столбца, вы можете передать вывод предыдущей команды в sort
:
awk '{ z[$1]=z[$1]$2 } END { for (i in z) print i, z[i] }' file1 file2 \
| sort -n -k1
Левое / правое внешнее объединение против полного внешнего объединения
Проблема с командой, которую вы используете, заключается в том, что она требует, чтобы все записи в файле2 находились в файле1. Раздел print инструкции оценивает только записи, которые находятся в file2.
FNR
и NR
часто используются таким образом для СОЕДИНЕНИЯ на основе общности - выбор всех записей из одного набора данных и только связанных записей из другого набора данных. То, что вы реализовали, - это, в частности, «ПРАВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ», поскольку оно будет извлекать все записи с «правой» стороны - file2 и соответствующие элементы левой стороны, file1.
Вместо этого вы хотите выполнить «ПОЛНОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ». Все записи в обоих файлах со слиянием записей на основе столбца 1.
FNR == NR
означает, что количество записей «FILE» ( FNR
) равно общему количеству Записи ( NR
). NR
будет увеличиваться для каждой строки из любого обрабатываемого файла, а FNR
сбрасывается в 0 при запуске нового файла. Таким образом, FNR == NR
верно только при импорте 2+ файлов при чтении первого файла. Когда awk переключается на следующий файл, FNR сбрасывается на 0, в то время как NR продолжает расти.
Чтобы проиллюстрировать это, я вставил оператор печати, чтобы предоставить состояние этих переменных, когда awk обрабатывает ввод:
$> awk 'FNR==NR{a[$1]=$2;printf("File: %s, NR: %s, FNR: %s, $1: %s, $2: %s, a[$1]: %s\n",FILENAME,NR,FNR,$1,$2,a[$1]); next} {printf("File: %s, NR: %s, FNR: %s, $1: %s, $2: %s, a[$1]$2: %s\n",FILENAME,NR,FNR,$1,$2,a[$1]$2); }' file1 file2
File: file1, NR: 1, FNR: 1, $1: 001, $2: A, a[$1]: A
File: file1, NR: 2, FNR: 2, $1: 002, $2: B, a[$1]: B
File: file1, NR: 3, FNR: 3, $1: 003, $2: C, a[$1]: C
File: file1, NR: 4, FNR: 4, $1: 004, $2: D, a[$1]: D
File: file2, NR: 5, FNR: 1, $1: 002, $2: D, a[$1]$2: BD
File: file2, NR: 6, FNR: 2, $1: 003, $2: D, a[$1]$2: CD
File: file2, NR: 7, FNR: 3, $1: 005, $2: E, a[$1]$2: E
File: file2, NR: 8, FNR: 4, $1: 006, $2: F, a[$1]$2: F
Решение
Чтобы исправить это, все, что вам нужно сделать, это продолжать добавлять записи в массив во время обработки file2, и выводить результаты только после обработки всех входных файлов.
Таким образом, в данном случае нас вообще не интересуют NR
или FNR
.
Для каждой строки текста из всех входных файлов используйте значение первого столбца $ 1
в качестве индекса в массиве a [$ 1]
Назначьте значение столбца 2, $ 2
в массив по этому индексу, но добавляем значение, чтобы мы не перезаписывали значение, которое, возможно, уже существует: a [$ 1] = a [$ 1] $ 2
Подождите, пока все записи / строк были обработаны перед печатью массива:
for (i in a) {printf ("% s \ t% s \ n", i, a [i])}
Единственный недостаток этого состоит в том, что awk использует ассоциативные массивы, которые используют строковые индексы, а не целые числа (вот почему это вообще работает), но побочным эффектом этого является то, что порядок записей в массиве может быть не таким, как задумано; в этом случае распечатка содержимого выполняется не в числовом порядке (по индексу), поэтому требуется конвейерная передача вывода для сортировки:
$> awk '{ a[$1]=a[$1]$2; next } END { for (i in a) { printf("%s\t%s\n", i, a[i]) } }' file1 file2 | sort -n
001 A
002 BD
003 CD
004 D
005 E
006 F
Альтернативный подход
Вы также можете использовать команду соединения для этого, но я не знаю, как чтобы заставить его объединить поля - они остаются разделенными пробелами, поэтому требуется дополнительный этап обработки:
$> join -o 0,1.2,2.2 -a1 -a2 file1 file2 | awk '{printf("%s\t%s%s\n", $1, $2, $3)}'
001 A
002 BD
003 CD
004 D
005 E
006 F
TODO
Это не делает ничего, чтобы отклонить повторяющиеся записи - что может быть или не быть желательным. В настоящее время, если у вас есть повторяющиеся записи в отдельных входных файлах, они будут объединены:
file1: 001 A
и
file2: 001 A
приведет к выходной записи
001 AA