
У меня есть входной CSV-файл, который выглядит следующим образом:
john,Hello my name
john,is John
katie,Whereas my
katie,name is Katie
bob,And I am Bob.
Файл упорядочен таким образом, что имена (в первом столбце) расположены последовательно, а текст (второй столбец) упорядочен логически.
Существует ли стандартизированный способ «группировать» (используя терминологию SQL) первый столбец и объединить второй столбец?
Мой желаемый результат:
john,Hello my name is John
katie,Whereas my name is Katie
bob,And I am Bob.
решение1
Расширенные знания длины каждого блока избавляют нас от незначительной сложности, связанной с граничным условием, которое в противном случае потребовало бы блока END с реплицированной функциональностью.
Я не защищаю этот подход в пользу принятого ответа Жиля. Я просто представляю его, чтобы продемонстрировать альтернативный подход, который при работе со сложными проблемами (эта не является одной из них) может дать значительное снижение сложности (за счет ввода-вывода и, возможно, памяти).
a
— это индексированный по имени массив длин блоков. n
— это количество оставшихся строк в блоке:
awk -F, '
FNR==NR {a[$1]++; next}
n {print " "$2}
!n {print; n=a[$1]}
!--n {print "\n"}
' ORS= data data
решение2
Для этого нет стандартного инструмента, нет. Эта задача вполне подходит для awk: читать строки одну за другой, сохранять первое поле и накапливать второе поле, и выводить результат, если первое поле изменяется. Основная (второстепенная) сложность в том, что результат также должен быть выведен при достижении последней строки.
awk -F, '
1 {current = $1; sub(/^[^,]*,/,"")}
current == previous {acc = acc " " $0; next}
NR != 1 {print previous "," acc}
1 {previous = current; acc = $0}
END {if (NR) print previous "," acc}'
решение3
awk -F, '{a[$1]=a[$1]? a[$1]" "$2 : $2;}END{for (i in a)print i, a[i];}' OFS=, filename