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