그룹별 AWK/KSH 셸 텍스트 처리/계산 [닫기]

그룹별 AWK/KSH 셸 텍스트 처리/계산 [닫기]

다음 내용을 포함하는 파일이 제공됩니다.

ID      NAME    COMPANY  YEAR
111     LUIS    TCS     2016
222     URSO    XYZ     2014
333     OMAR    ABC     2015
444     SANJIB  MABE    2012
111     LUIS    TCS     2015
444     SANJIB  MABE    2011
111     LUIS    TCS     2015
222     URSO    XYZ     2015
333     OMAR    ABC     2014

먼저 ID별로, 그 다음에는 연도별로 두 가지 정렬이 필요하며 지금까지 성공적으로 수행했습니다. 다음 단계는 아래와 같이 동일한 ID의 각 발생 횟수를 포함하는 추가 열을 추가하는 것입니다.

ID      NAME    COMPANY  YEAR   Count
111     LUIS    TCS     2015    1
111     LUIS    TCS     2015    2
111     LUIS    TCS     2016    3
222     URSO    XYZ     2014    1
222     URSO    XYZ     2015    2
333     OMAR    ABC     2014    1
333     OMAR    ABC     2015    2
444     SANJIB  MABE    2011    1
444     SANJIB  MABE    2012    2

등.

미리 감사드립니다.

답변1

아마도:

< file sort | awk '{print $0 "\t" ++n[$1]}'

답변2

제공된 샘플 데이터에 대한 단일 정렬은 요청한 출력과 동일한 순서로 출력을 반환합니다. 머리글 행이 정렬에 포함되지 않는다고 가정합니다.

sort datafile

다음 단계는 열 5에 동일한 ID가 표시되는 횟수를 세는 것입니다. 또한 새로운 5번째 열을 포함하도록 헤더를 교체합니다.

우리는 awk 구문 분석에서 원래 헤더 라인을 건너뛰고 싶습니다.

awk 'BEGIN {print "ID\tNAME\tCOMPANY\tYEAR\tCOUNT"} NR>1 {id_count[$1]++; print $0 "\t" id_count[$1]}' datafile

데이터 파일의 첫 번째 줄이 헤더인 경우 awk는 해당 줄을 무시합니다(줄/레코드 번호가 1보다 커야 함).

첫 번째 명령을 두 번째 명령으로 파이프하여 명령을 합치면 됩니다. 다음 예에서는 헤더 행이 정렬된 출력에 포함되지 않는다고 가정합니다.

sort datafile | awk 'BEGIN {print "ID\tNAME\tCOMPANY\tYEAR\tCOUNT"}  {id_count[$1]++; print $0 "\t" id_count[$1]}'

정렬 명령 자체에는 모든 필드가 포함되어 있으므로 열별로 정렬하고 ID, 이름, 회사, 연도를 함께 입력하게 됩니다. awk 명령은 새 헤더를 인쇄하고(원래 헤더를 어느 정도 복사함) COUNT 열을 추가합니다.

연관 배열을 사용하여 필드 1(ID)을 확인하여 데이터의 나머지 행을 구문 분석합니다. 각 행은 탭과 함께 있는 그대로 인쇄되며 열 1이 추가된 횟수를 표시합니다.

최종 print 문은 처음에는 혼란스러울 수 있지만 awk의 공백 문자는 조인 문자입니다. $0, 탭 문자, 변수 값은 모두 출력에 함께 압축됩니다. 이를 작성하는 또 다른 방법은 다음과 같습니다.

printf "%s\t%d\n",$0,id_count[$1]

답변3

Stefan Chazeras의 답변괜찮습니다. 하지만 데이터 제목을 무시합니다. 또한 특정 항목이 ID항상 동일한 NAME합계 에 해당한다고 가정합니다 COMPANY.

그렇지 않은 경우에는 약간 다른 작업을 수행해야 합니다.

sort -k1,1 -k4,4 file.in | awk '{ print $0, ++n[$1] }'

제목을 올바르게 작성하려면 다음을 수행하십시오.

sed '1d' file.in |
sort -k1,1 -k4,4 |
awk -vOFS="\t" \
   'BEGIN { print "ID", "NAME", "COMPANY", "YEAR", "Count" }
          { print $0, ++n[$1] }'

이렇게 하면 입력에서 헤더가 제거되고, 파일이 정렬되고 ID, YEAR새 열과 함께 헤더가 다시 삽입됩니다 Count. 그런 다음 각 입력에 대한 카운터를 증가시키고 ID각 입력 행의 마지막 열에 해당 카운터의 현재 값을 출력합니다.

ID      NAME    COMPANY YEAR    Count
111     LUIS    TCS     2015    1
111     LUIS    TCS     2015    2
111     LUIS    TCS     2016    3
222     URSO    XYZ     2014    1
222     URSO    XYZ     2015    2
333     OMAR    ABC     2014    1
333     OMAR    ABC     2015    2
444     SANJIB  MABE    2011    1
444     SANJIB  MABE    2012    2

awk파일에서 원래 헤더를 선택하고 Count명시적으로 다시 입력할 필요 없이 헤더만 추가하려는 경우 다음과 같이 할 수도 있습니다.

sed -e '1w /tmp/header.txt' -e '1d' file.in |
sort -k1,1 -k4,4 |
awk -vOFS="\t" \
   'NR == 1 { getline h <"/tmp/header.txt"; print h, "Count" }
            { print $0, ++n[$1] }'

rm -f /tmp/header.txt

이로 인해 sed헤더가 파일에 기록됩니다 /tmp/header.txt. 첫 번째 레코드를 읽으면 awk파일을 변수로 읽어서 h새 열과 함께 출력합니다 Count. 나머지 스크립트는 awk이전과 같이 작동하며 동일한 출력을 생성합니다.

이 파일은 첫 번째 입력 레코드가 도착할 때까지 읽혀지지 않으므로 스크립트가 읽을 수 있도록 /tmp/header.txt존재하는 것이 보장됩니다 . awk이 시점에서 sort모든 입력이 소비되었습니다. sed즉, 헤더 파일이 작성되었음을 의미합니다. 블록에서 읽는 것이 BEGIN가능합니다.아니요일하다.

관련 정보