Uma solução awk
ligeiramente longa (mas, esperamos, fácil de seguir):
BEGIN { FS = OFS = "|" }
function output() {
if (FNR == 1) return
data = ""
for (i in col2) {
qi = sprintf("'%s'", i);
data = (data == "" ? qi : data "," qi)
}
print col1, sprintf("{%s}", data), col3
}
$1 == col1 && !($2 in col2) { col2[$2] }
$1 != col1 {
output()
col1 = $1; col3 = $3
delete col2; col2[$2]
}
END { output() }
O bloco BEGIN
apenas define o separador de campos de entrada e saída como |
.
A função output()
terá os dados recolhidos em col1
(a ID da primeira coluna), col2
(uma matriz de dados originais formar a segunda coluna) e col3
(o primeiro item de dados para esse ID específico da terceira coluna) e imprimi-lo. Ele itera sobre as chaves em col2
, citando-los individualmente e adicionando-os com vírgulas no meio para a variável de cadeia data
. Em seguida, imprime col1
, data
(dentro de chaves), e col3
.
O próximo bloco é executado quando encontramos uma entrada na segunda coluna que não vimos antes para esse ID específico. Apenas adiciona a segunda coluna como uma chave em col2
.
O bloco depois disso é executado quando encontramos um novo ID na primeira coluna. Ele chama output()
e redefine as variáveis coletadas para começar a coletar dados para esse novo ID.
No bloco END
, chamamos output()
para a saída dos dados para o último ID.
Este programa não irá tentar armazenar o arquivo inteiro na memória de uma só vez, mas exige que os dados são classificados na primeira coluna.
Executando nos dados fornecidos:
$ awk -f script.awk file
field11|{'field12','field32'}|field13
field41|{'field42','field62','field52'}|field43