awk는 다른 열에 해당 행을 추가합니다.

awk는 다른 열에 해당 행을 추가합니다.

Presidents.txt라는 파일이 있습니다. 내용은 다음과 같습니다...

First  Last  Age  Years
Geogre W     57   8.0
John   A     61   4.0
Thomas J     57   8.0
James  M     57   8.0
Andrew J     61   8.0

나에게 필요한 것은 각 대통령의 나이와 연수를 추가할 수 있는 프로그램이다. 예를 들어 George W는 57+8.0, John A는 61+4.0 등입니다. 각 대통령의 번호를 합산한 후, 프로그램은 가장 높은 번호를 가진 대통령의 이름을 출력합니다. 예를 들어, 여기서 출력은 "Andrew J at 69"여야 합니다. 지금까지는 각 대통령에 대해 한 번에 하나씩 이 작업을 수행할 수 있지만 awk 루프를 사용하여 수행하고 싶습니다. 지금까지 내가 사용한 명령은 다음과 같다.

awk 'NR==2 {print $3+$4}' presidents.txt

이것은 숫자 61과 4.0을 추가하여 출력 65를 제공하며 이것이 시작이라고 생각합니다. 루프와 배열을 사용해야 한다고 확신하지만 일반적으로 Unix나 코딩에 대한 경험이 많지 않기 때문에 어디서부터 시작해야 할지 모르겠습니다. 도움을 주시면 감사하겠습니다.

답변1

$3+$4에 대한 중복 결과가 있을 때 입력에서 해당 결과의 마지막 발생만 인쇄하려고 한다고 가정합니다.

$ cat tst.awk
NR>1 {
    curYear = $3 + $4
    if ( curYear >= maxYear ) {
        maxName = $1 OFS $2
        maxYear = curYear
    }
}
END {
    print maxName, "at", maxYear
}

$ awk -f tst.awk file
Andrew J at 69

예를 들어, 수정된 입력 파일에서 2명( Andrew JSheila E) 모두 총 값이 $3+$4(69)인 경우:

$ cat file
First  Last  Age  Years
Geogre W     57   8.0
John   A     61   4.0
Thomas J     57   8.0
James  M     57   8.0
Andrew J     61   8.0
Sheila E     65   4.0

위 스크립트를 사용하여 최종 출력을 얻습니다.

$ awk -f tst.awk file
Sheila E at 69

어쩌면 당신은 첫 번째 것을 원할 수도 있습니다.

$ cat tst.awk
NR>1 {
    curYear = $3 + $4
    if ( curYear > maxYear ) {
        maxName = $1 OFS $2
        maxYear = curYear
    }
}
END {
    print maxName, "at", maxYear
}

$ awk -f tst.awk file
Andrew J at 69

또는 모두:

$ cat tst.awk
NR>1 {
    curYear = $3 + $4
    if ( curYear >= maxYear ) {
        if ( curYear > maxYear ) {
            numNames = 0
        }
        maxNames[++numNames] = $1 OFS $2
        maxYear = curYear
    }
}
END {
    for ( nameNr=1; nameNr<=numNames; nameNr++ ) {
        print maxNames[nameNr], "at", maxYear
    }
}

$ awk -f tst.awk file
Andrew J at 69
Sheila E at 69

답변2

awk다음 과 결합 sort:

awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | head -1
Andrew J at 69

나이와 연도의 합계를 마지막 필드로 사용하여 중간 파일을 만든 다음 마지막 필드, 숫자 및 역순을 sort사용 하고 마지막으로 첫 번째 줄만 인쇄합니다 .k4nrhead


이는 최대 연도가 여러 행인 경우를 처리하기 위한 개선 사항입니다. 우리는 그것들을 모두 인쇄합니다:

awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | uniq -f3 --group | sed '/^$/q'

uniq중복 행이 그룹화되고(첫 번째 3 f필드 무시, 즉 마지막 숫자만 테스트됨) 그룹을 빈 행으로 구분하고 첫 번째 빈 행에 첫 번째 그룹만 인쇄합니다 sed.q

답변3

이 작업을 수행하려면 루프나 배열이 필요하지 않습니다. 노력하다:

awk '
            { name= $1 OFS $2 OFS "at" OFS }
NR>1        { age=$3+$4 }
age>ageMax  { ageMax=age; data=name; next }
age==ageMax { data= data ageMax ORS name }
END{ print data ageMax }' infile
  • { name= $1 OFS $2 OFS "at" OFS }향후 처리를 위해 이름과 성 부분을 기록하세요 .

  • 헤더 줄을 건너뛰고 "연도"에 "Age"를 추가하세요 NR>1{ age=$3+$4 }.

  • "age" 값이 "ageMax"보다 큰 경우 "ageMax" 값을 "age" 값으로 업데이트하고 "data"를 "name"으로 업데이트합니다 age>ageMax { ageMax=age; data=name; next }. 이 next명령문은 awk에 나머지 코드 처리를 건너뛰도록 지시합니다. 현재 행, awk는 다음 행을 읽습니다. 한 행이 처리됩니다.

  • 동일한 최대 AgeMax 값을 찾으면 해당 값을 "data" 값에 추가하여 모든 값을 유지합니다 age==ageMax { data= data ageMax ORS name }. 모두 필요하지 않은 경우 코드의 이 부분을 제거하면 ageMax가 가장 높은 첫 번째 레코드가 반환되거나 ageMax가 가장 높은 마지막 레코드가 반환 age>ageMax되는 것으로 대체됩니다.age>=ageMax

  • 에서는 END{ print data ageMax }결과를 인쇄합니다.

관련 정보