Вот сценарий awk. Просто измените число 5
, чтобы иметь другие группы.
awk '
NR==1{
previous = $1
for(i = 1;i<=NF+1;i++)
if($i!=previous){
col[++numcol] = i
previous = $i
}
}
{ j = 1; start = 1
for(i = 1;i<NF;i++){
printf "%s",$i
if(i==col[j]-1){printf " "; start = col[j++]}
else if((i-start+1)%5==0)printf " "
}
printf "%s\n",$NF
}'
Первая часть просто обрабатывает строку 1 и собирает в массиве col
начальный столбец для каждого набора одинаковых чисел. Вторая часть печатает каждое поле без разделения, за исключением столбца 5 от начального столбца или в конце последовательности.
Попробуйте это:
awk '
FNR==NR {seen[$2,$3]=1; print $0 }
FNR!=NR && !seen[$1,$2] { print 2019,$0,0 }
' file1 file2
Пояснение:
FNR==NR {... }
Запускайте команды в скобках только для первого файла. seen[$2,$3]=1
, установить массив seen
с ключами $2,$3 в 1. print $0
напечатать всю строку. FNR!=NR && !seen[$1,$2] {... }
Выполнять команды в скобках только если не первый файл и если поля $1,$2 не являются ключами в массиве seen
. print 2019,$0,0
напечатать строку, окруженную новыми столбцами 2019 и 0. Добавьте | column -t
для выровненного вывода.
Выход:
$ awk 'FNR==NR{seen[$2,$3]++; print $0} FNR!=NR && !seen[$1,$2]{print 2019,$0,0}' file1 file2 | column -t
2019 ABCD 1 10
2019 DEF 2 11
2019 GHI 1 20
2019 jkl 2 25
2019 jkl 1 0
2019 mnop 2 0
2019 qrst 1 0
Это должно работать:
$ awk 'NR==FNR{a[$2$3]++; print; next}!($1$2 in a){print "2019",$0,"0"}' file1 file2
2019 ABCD 1 10
2019 DEF 2 11
2019 GHI 1 20
2019 jkl 2 25
2019 jkl 1 0
2019 mnop 2 0
2019 qrst 1 0
NR==FNR
:NR — номер текущей строки, FNR — номер строки текущего файла. Они будут идентичны только во время чтения первого файла. {a[$2$3]++; print; next}
:при чтении первого файла(file1
)использовать 2-е и 3-е поля в качестве ключа для ассоциативного массива a
. Это просто используется, чтобы отслеживать, какие из них мы уже видели. Затем распечатайте эту строку и перейдите к следующей. Это next
гарантирует, что остальная часть скрипта будет выполняться только для второго файла, когда NR
не совпадает с FNR
. !($1$2 in a)
:если первое и второе поля этой строки не используются в качестве ключей в массиве a
(, это означает, что 1-е и 2-е поля объединены, поэтому, если 1-е это foo
и второе bar
, $1$2
будетfoobar
). {print "2019",$0,"0"}
:напечатать 2019
, текущую строку из file2
и 0
. Вот совсем другой способ сделать это:
mkns() {
# make keys from parameters $2 and $3 for joining, then sort the keys
sort -k 1b,1 <(awk "{print \$$2\$$3, \$0}" $1)
}
Затем запустите
join -j 1 -v 2 <(mkns file1 2 3) <(mkns file2 1 2) | awk '{print 2019, $2, $3, 0}' | cat file1 - | column -t
Это не так коротко, как чисто awk
решения от RoVo и Tendon, но я думаю, что это интересное решение, потому что join
можно использовать для «отфильтровывания» нужных вам строк.