Aqui está a mesma ideia básica da solução de Glenn, mas em Perl:
$ perl -F";" -lane '$"=";";print "@F[0..3];", $_ for @F[4..$#F]' file
ID ;email ;role ;privilege ;access-to
8charID1 ;[email protected] ;usr ;read ;finance
8charID1 ;[email protected] ;usr ;read ;HR
8charID1 ;[email protected] ;usr ;read ;accounting
8charID1 ;[email protected] ;usr ;read ; dev
8charID2 ;[email protected] ;mgr ;rwx ;finance
8charID3 ;[email protected] ;usr ;rx ;marketing
8charID3 ;[email protected] ;usr ;rx ;dev
8charID3 ;[email protected] ;usr ;rx ;doc
Explicação
-
-a
: faz o perl agir como awk
, dividindo automaticamente cada linha em campos no espaço em branco (por padrão, veja -F
) e salvando-os na matriz @F
.
-
-e
: permite que você forneça um script na linha de comando.
-
-n
: leia o arquivo de entrada linha por linha.
-
-l
: remova as novas linhas iniciais e adicione uma nova linha a cada chamada print
.
-
-F
: como awk
, o separador de campo de entrada. Aqui, estamos configurando para ;
.
O script é reconhecidamente meio enigmático, mas o algoritmo é muito simples: imprima os quatro primeiros campos e repita para cada campo > 4.
-
$"=";"
: A variável especial $"
é o separador de lista. Isso é impresso entre cada elemento de uma matriz de você imprimir a matriz. Aqui, estou configurando para ;
, para que possamos obter a lista de campos impressos conforme desejado.
-
@F[0..3]
: esta é uma fatia da matriz. São os primeiros 4 elementos da matriz @F
(os campos ;
-separados da linha atual)
-
@F[4..$#F]
: outra fatia da matriz. Este é do 5º elemento de @F
até o último ( $#array
é o maior índice de um array em Perl).
O comando print inteiro é apenas idiomático Perl para:
## For each element of the array slice
foreach $field (@F[4..$#F]){
## print the first 4 fields and a ';', The fields
## are printed separated by ";" because of the $" above.
print "@F[0..3];";
## In the golfed version, the $_ is equivalent to $field here
print "$field\n"
}