Analisa vários milhares de linhas de txt em linhas e colunas

2

O arquivo em questão lista nomes, credenciais, funções e privilégios para milhares de usuários. Foi passado para mim como xls, mas as linhas e colunas não estão dispostas na forma adequada. Eu reformatei o arquivo raw usando o awk e sed, agora eu tenho um número de linhas com formato consistente como tal:

ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance ;HR ;accounting; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing ;dev ;doc
.
.
n x 1,000 number of users

Mas estou preso no próximo passo.

Objetivo: reimprima as linhas de forma que, quando houver vários campos de acesso como a linha 1 ou a linha 3, todos os campos precedentes sejam reimpressos por número de campo de acesso e reordene o campo de acesso em uma coluna SINGLE.

ID       ;email                     ;role  ;privilege ;access-to
abcuser1 ;[email protected] ;usr   ;read      ;finance
abcuser1 ;[email protected] ;usr   ;read      ;HR
abcuser1 ;[email protected] ;usr   ;read      ;accounting
abcuser1 ;[email protected] ;usr   ;read      ;dev
user2def ;[email protected] ;mgr   ;rwx       ;finance
zyxuser3 ;[email protected] ;usr   ;rx        ;marketing
zyxuser3 ;[email protected] ;usr   ;rx        ;dev
zyxuser3 ;[email protected] ;usr   ;rx        ;publication
.
.
.
n x 1,000 number of users
    
por user2793091 05.11.2014 / 20:05

2 respostas

2
awk -F';' -v OFS=';' '
    { for (i=5; i<=NF; i++) print $1,$2,$3,$4,$i }
' file

saídas

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
    
por 05.11.2014 / 20:25
2

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"
}
    
por 05.11.2014 / 21:08