현재 문서에는 수천 명의 사용자의 이름, 자격 증명, 역할 및 권한이 나열되어 있습니다. .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
: 입력 파일을 한 줄씩 읽습니다.-l
print
: 후행 줄바꿈을 제거하고 각 호출에 줄바꿈을 추가합니다.-F
: 와 마찬가지로awk
입력 필드 구분 기호입니다. 여기서는 으로 설정했습니다;
.
물론 스크립트는 약간 난해하지만 알고리즘은 매우 간단합니다. 처음 4개의 필드를 인쇄하고 각 필드에 대해 >4를 반복합니다.
$"=";"
: 특수 변수는$"
목록 구분 기호입니다. 이는 배열을 인쇄할 때 배열의 각 요소 사이에 인쇄됩니다. 여기서는;
필요한 경우 필드 목록을 인쇄할 수 있도록 설정했습니다 .@F[0..3]
: 배열 슬라이스입니다. 배열의 처음 4개 요소입니다@F
(;
현재 행의 - 구분된 필드).@F[4..$#F]
: 또 다른 배열 슬라이스. 이는 5번째 요소부터@F
마지막 요소($#array
Perl에서 배열의 최대 인덱스)까지입니다.
전체 인쇄 명령은 단지 관용적인 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"
}