Ваша awk
программа верна, если мы изменим ее на безусловно используем
print $0","( a[$3] ? a[$3] : 0 )
вместо использования
print $0","a[$3]
, когда a[$3]
не равен -нулю или пуст. То есть используйте ноль, если поле a[$3]
равно нулю или пусто, в противном случае используйте a[$3]
.
Другими словами,
awk -F, -v OFS=',' 'FNR==NR { a[$1]=$2; next } FNR > 1 { print $0, (a[$3] ? a[$3] : 0) }' fileB fileA
Здесь мы используем FNR > 1
, чтобы пропустить заголовок.
Использованиеjoin
:
$ join -t, -1 3 -o 1.1,1.2,1.3,1.4,2.2 fileA fileB
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
Если файлы не отсортированы по ключу соединения, то (в оболочке, поддерживающей подстановки процессов):
$ join -t, -1 3 -o 1.1,1.2,1.3,1.4,2.2 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
4,1993,6050,912432,1.8 GHz
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
join
выполнит операцию INNER JOIN
над двумя файлами. -t,
сообщает join
, что запятые являются разделителем полей, и мы выбираем третье поле в качестве ключа соединения в первом файле с-1 3
(первое поле во втором файле считается ключом, если мы не используем -2 N
для того же другого поля N
в этом файле ).
Флаг -o
сообщает join
, какие поля мы хотели бы включить в вывод и из какого файла(x.y
означает столбец y
из файлаx
).
join
— очень быстрая операция, но она требует сортировки входных файлов по ключу соединения (нам просто повезло с первым примером выше ). Окончательный вывод во втором примере выше не отсортирован по отношению к первому полю , но вы можете легко исправить это, передав его через sort -k1,1n
.
Для второго сценария с несоответствием
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -a 1 -e 0 <( sort -t, -k3,3 fileA ) <( sort fileB )
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
4,1993,6050,912432,1.8 GHz
A,B,C,D,0
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
Добавляя -a 1 -e 0
, мы просим join
всегда выводить все поля из первого файла(-a 1
)и вставлять нули для каждого поля, отсутствующего во втором файле.
Как видите, теперь мы получаем правильный результат, но заголовок из первого файла также включен (, потому что мы просили об этом ). Если вы хотите удалить заголовки из данных обоих файлов (и отсортировать результат ), то
$ join -t, -1 3 -o1.1,1.2,1.3,1.4,2.2 -e 0 -a1 <( tail -n +2 fileA | sort -t, -k3,3 ) <( tail -n +2 fileB | sort ) | sort -k1,1n
1,1990,I001,2473264,2.3 GHz
2,1991,I002,2473265,2.3 GHz
3,1992,I004,2473266,2.3 GHz
4,1993,6050,912432,1.8 GHz
5,1994,6003,912433,850 MHz
6,1995,6004,21234,0
Эта команда будет работать в обоих сценариях.
Нет, базовая структура оператора case такова, что выполняется только один соответствующий сегмент. За исключением падения -, через которое вы отвергаете. Кроме того, он работает только с некоторыми оболочками, а не со всеми, и имеет синтаксис, специфичный для каждой оболочки. Синтаксис Bash для перехода с -на конец — ;;&
. В ksh или zsh единственный доступный ;&
не выполняет следующий тест, только непосредственное выполнение сегмента (будет печатать обе строки для всех случаев вTue|Wed|Thu|Fri
).
Единственный вариант для кейса — разбить его на две строки:
esac
case $now in
Как это (Пожалуйста!, оставьте переменные в ПРОПИСНЫХ РЕГИСТРАХ для переменных окружения):
#!/bin/bash
now=$(date +"%a")
case $now in
Mon)
echo "Mon";;
Tue|Wed|Thu|Fri)
echo "Tue|Wed|Thu|Fri";;
esac
case $now in
Fri|Sat|Sun)
echo "Fri|Sat|Sun";;
*) ;;
esac
Другой вариант :использования функций.
$ cat tt
#!/bin/bash
mon() { echo " Mon" ; }
tue_fri() { echo " Tue|Wed|Thu|Fri" ; }
fri_sun() { echo " Fri|Sat|Sun" ; }
now=$(date +"%a")
[[ $1 != "" ]] && now=$1 # use for testing
case $now in
Mon) mon ;;
Tue|Wed|Thu) tue_fri ;;
Fri) tue_fri; fri_sun ;;
Sat|Sun) fri_sun ;;
*) echo " ERROR" ;;
esac
и проверьте с помощью
$ for f in Mon Tue Wed Thu Fri Sat Sun bla ;do echo "$f"; tt "$f"; done
Mon
Mon
Tue
Tue|Wed|Thu|Fri
Wed
Tue|Wed|Thu|Fri
Thu
Tue|Wed|Thu|Fri
Fri
Tue|Wed|Thu|Fri
Fri|Sat|Sun
Sat
Fri|Sat|Sun
Sun
Fri|Sat|Sun
bla
ERROR