수천 줄의 txt를 행과 열로 구문 분석합니다.

수천 줄의 txt를 행과 열로 구문 분석합니다.

현재 문서에는 수천 명의 사용자의 이름, 자격 증명, 역할 및 권한이 나열되어 있습니다. .xls로 전달됐는데 행과 열이 올바른 형식으로 정렬되지 않았습니다. awk 및 sed를 사용하여 원본 파일의 형식을 다시 지정했으며 이제 다음과 같은 일관된 형식의 줄이 많이 있습니다.

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

하지만 다음 단계에서 막혔어요.

목표: 액세스된 필드가 여러 개 있는 경우(예: 행 1 또는 행 3) 행을 다시 인쇄하고 액세스된 필드 수를 기준으로 이전의 모든 필드를 다시 인쇄하고 액세스된 필드를 단일 열로 재정렬합니다.

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

답변1

awk -F';' -v OFS=';' '
    { for (i=5; i<=NF; i++) print $1,$2,$3,$4,$i }
' 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

답변2

Glenn의 솔루션과 동일한 기본 아이디어가 있지만 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

설명하다

  • -a: Perl을 처럼 동작하게 만들어 awk자동으로 각 줄을 공백의 필드로 분할하고(기본적으로 참조 -F) @F배열에 저장합니다.
  • -e: 명령줄에 스크립트를 제공할 수 있습니다.
  • -n: 입력 파일을 한 줄씩 읽습니다.
  • -lprint: 후행 줄바꿈을 제거하고 각 호출에 줄바꿈을 추가합니다.
  • -F: 와 마찬가지로 awk입력 필드 구분 기호입니다. 여기서는 으로 설정했습니다 ;.

물론 스크립트는 약간 난해하지만 알고리즘은 매우 간단합니다. 처음 4개의 필드를 인쇄하고 각 필드에 대해 >4를 반복합니다.

  • $"=";": 특수 변수는 $"목록 구분 기호입니다. 이는 배열을 인쇄할 때 배열의 각 요소 사이에 인쇄됩니다. 여기서는 ;필요한 경우 필드 목록을 인쇄할 수 있도록 설정했습니다 .

  • @F[0..3]: 배열 슬라이스입니다. 배열의 처음 4개 요소입니다 @F( ;현재 행의 - 구분된 필드).

  • @F[4..$#F]: 또 다른 배열 슬라이스. 이는 5번째 요소부터 @F마지막 ​​요소( $#arrayPerl에서 배열의 최대 인덱스)까지입니다.

전체 인쇄 명령은 단지 관용적인 Perl 명령입니다:

## 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"
}

관련 정보