#arrays #awk
Вопрос:
Скорее всего, это делается с помощью массивов, но я не знаю, как построить логику.
Ввод:
uid1 ip1 tag1
uid1 ip1 tag2
uid2 ip2 tag3
uid2 ip2 tag4
uid2 ip2 tag5
Желаемый результат:
uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5
Я думаю, что , возможно , этого можно достичь, сохранив все элементы в array1
, затем uid
ip
поля в array2
, а затем выполнив поиск array1
путем повторения элементов из array2
.
Ответ №1:
awk -v OFS=, '{
k=$1 SUBSEP $2;
arr[k] = k in arr ? arr[k] OFS $3 : $0;
}
END{
for(i in arr)
print arr[i]
}' infile
Результаты испытаний:
$ cat f1
uid1 ip1 tag1
uid1 ip1 tag2
uid2 ip2 tag3
uid2 ip2 tag4
uid2 ip2 tag5
$ awk -v OFS=, '{k=$1 SUBSEP $2; arr[k] = k in arr ? arr[k] OFS $3 : $0;}END{for(i in arr)print arr[i]}' f1
uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5
Объяснение:
awk -v OFS=, '{ # output field separator
# variable k contains field1 value
# and SUBSEP - Multi-dimensional array separator
# and column 2 value
k=$1 SUBSEP $2;
# arr -> array
# if array key that is variable k already exists in array arr
# then arr[k] will be existing content of arr[k] plus
# field separator (comma) and then field 3 contents
# else entire row/record which is when array does not have index already
arr[k] = k in arr ? arr[k] OFS $3 : $0;
}
END{ # END block
# iterate through array arr
# and print array value
for(i in arr)
print arr[i]
}' infile
Троичный оператор ниже
arr[k] = k in arr ? arr[k] OFS $3 : $0;
Это то же самое, что
if(k in arr){
arr[k] = arr[k] OFS $3
}else{
arr[k] = $0
}
Комментарии:
1. Спасибо, все сработало так, как задумывалось. Я не могу сказать, что могу расшифровать весь код, чтобы лучше понять, как он работает. В частности, эти части:
k=$1 SUBSEP $2
иarr[k] = k in arr ? arr[k] OFS $3 : $0
2. @однострочное добавленное объяснение
3. @Akshay, Спасибо, что поделился приятным ответом «Ура».
4. Действительно очень хорошо объяснено
Ответ №2:
С помощью GNU datamash
$ datamash -W -t' ' -g1,2 collapse 3 <ip.txt
uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5
-W
чтобы использовать пробел/вкладку в качестве разделителя полей ввода-t' '
пробел в качестве разделителя выходных полей-g1,2
группа на основе полей1
и2
collapse 3
операция, которая будет выполнена на поле3
Комментарии:
1. Я не знал об
datamash
этом , синтаксис выглядит намного проще и чище, к сожалению, он не установлен по умолчанию в моей целевой среде. Будем иметь это в виду, однако, для использования в будущем.