awk와 함께 printf를 사용하여 명령 출력을 구분하는 열을 지정하는 방법

awk와 함께 printf를 사용하여 명령 출력을 구분하는 열을 지정하는 방법

다음과 같이 출력에서 ​​제조업체 이름, 펌웨어 버전 및 카드 상태를 추출하고 싶습니다 fcinfo hba-port.

루트-#> fcinfo HBA 포트
HBA 포트 WWN: 10000000c96a53c5
        운영 체제 장치 이름: /dev/cfg/c2
        제조사 : Emulex
        모델: LPe11000-M4
        펌웨어 버전: 2.82a4(Z3D2.82A4)
        FCode/BIOS 버전: 부팅: 5.02a1 Fcode: 1.50a9
        일련번호: VM73059524
        드라이버 이름: emlxs
        드라이버 버전: 2.60k (2011.03.24.16.45)
        유형: N 포트
        상태: 온라인
        지원 속도: 1Gb 2Gb 4Gb
        현재 속도: 4GB
        노드 WWN: 20000000c96a53c5

다음 방법을 사용하여 이 세 가지 필드를 추출합니다 awk.

root-#> fcinfo hba-port | awk '/Manufacturer:/{m=$2}/Firmware Version:/{F=$3}/State/{print m, F, $2}'
Emulex 2.82a4 online
Emulex 2.82a4 online
Emulex 2.82a4 offline
Emulex 2.82a4 offline
Emulex 2.82a4 online
Emulex 2.82a4 online

예를 들어 다음과 같이 좀 더 사용자 친화적인 형식으로 출력을 제시하고 싶습니다.

HBA_Manufacturer    Firmware_Version   State
--------------------------------------------
Emulex               2.82a4           online
Emulex               2.82a4           offline
Emulex               2.82a4           offline

...제목을 추가하고 데이터에 맞춰 정렬합니다. 어떻게 해야 하나요?

Solaris 솔루션이 필요합니다. (Linux에 적용되는 많은 명령이 Solaris에는 적용되지 않습니다.)

답변1

다음 명령을 사용하지 않고도 열 을 column내부적으로 완전히 정렬 할 수 있습니다.awk

# fcinfo hba-port | awk '
                        BEGIN{man[-1]="HBA_Manufacturer"
                              ver[-1]="Firmware_Version"
                              sta[-1]="State"
                              man[0]="----------------"
                              ver[0]="----------------"
                              sta[0]="-----"
                              i=1
                             }
                        /Manufacturer:/     {man[i]=$2}
                        /Firmware Version:/ {ver[i]=$3}
                        /State:/            {sta[i]=$2; i++}
                        END {
                             maxlen1 = maxlen2 = maxlen3 = 0
                             for (j=-1; j<i; j++) {
                                 if (length(man[j]) > maxlen1) maxlen1 = length(man[j])
                                 if (length(ver[j]) > maxlen2) maxlen2 = length(ver[j])
                                 if (length(sta[j]) > maxlen3) maxlen3 = length(sta[j])
                             }
                             for (j=-1; j<i; j++) {
                                 printf("%-*s  %-*s  %-*s\n", maxlen1, man[j],
                                                              maxlen2, ver[j],
                                                              maxlen3, sta[j])
                             }
                            }'

이는 전체 입력 텍스트를 읽고 데이터(제목 포함)를 man, versta(제조업체, 버전 및 상태) 배열에 저장합니다. 열 헤더는 항목에 배치되고 [-1]대시(헤더와 데이터 사이에 줄을 형성)는 [0]항목에 배치됩니다. 이는 출력의 처음 두 줄이 됩니다(아래 참조). 실제 데이터는 로 시작합니다 [1].

데이터 끝에 도달하면 각 열(헤더 포함)의 데이터 최대 길이를 결정한 다음 계산된 열 너비를 사용하여 배열의 모든 데이터를 인쇄합니다.

  • printf("%16s", "Emulex")인쇄합니다           Emulex (앞에 10개의 공백, 그 뒤에 6자의 이름, 총 16자).
  • printf("%-16s", "Emulex")(알아채다-)가 인쇄됩니다 Emulex           (6자리 이름과 10개의 후행 공백, 총 16자).
  • printf("%-*s", 16, "Emulex")형식 문자열 대신 printf("%-16s", "Emulex")매개변수 목록에서 가져오는 것을 제외 하고는 동일한 작업을 수행합니다 .16
  • 따라서 위의 내용은 다음과 유사한 출력을 생성합니다.

    HBA_Manufacturer  Firmware_Version  State
    ----------------  ----------------  -----
    Emulex            2.82a4            online
    Emulex            2.82a4            online
    Emulex            2.82a4            offline
    Emulex            2.82a4            offline
    Emulex            2.82a4            online
    Emulex            2.82a4            online
    

    열 사이에 더 많은 공간을 원할 경우 printf형식에 공백을 추가하세요. 예를 들어 "%-*s %-*s %-*s\n" , 보여준 예제 출력에 더 가까운 것을 제공할 것입니다 .

  • 표시된 예제 출력에는 제목 뒤에 연속적인 대시 줄이 있습니다. 위에 표시된 대로 내 명령은 각 제목 아래에 작은 대시 줄만 제공합니다. 일부 데이터가 더 길면 이는 더욱 분명해집니다.

    HBA_Manufacturer         Firmware_Version  State
    ----------------         ----------------  -----
    Emulex                   2.82a4            online
    Emulex                   2.82a4            online
    Some_other_manufacturer  2.82a4            offline
    Emulex                   2.82a4            offline
    Emulex                   2.82a4            online
    Emulex                   2.82a4            online
    

    필요한 경우 이 문제를 해결할 수 있습니다.

  • 입력 데이터가 크면 awk모든 데이터를 저장할 공간이 부족할 수 있으므로 이 작업이 실패할 수 있습니다.
  • 이전 버전 awk(예: Solaris)을 사용하는 경우 구문 오류로 인해 실패할 수 있습니다. 이런 일이 발생하면 printf다음과 같이 모든 명령문을 한 줄에 입력해 보세요.
          printf("%-*s %-*s %-*s\n", maxlen1, man[j], maxlen2, ver[j], maxlen3, sta[j])

답변2

각 열의 원하는 너비가 미리 결정되어 있는 경우awk가지다printf예를 들어 20자, 15자, 10자(사이에 공백 2개 포함)의 열을 원하는 경우 C와 매우 유사하게 작동합니다.

(as in Q)  /State/{printf "%-20s  %-15s  %-10s\n", m, F, $2}

( -왼쪽 정렬을 제공합니다. 기본값은 오른쪽입니다. 일반적으로 숫자에는 작동하지만 텍스트에는 작동하지 않습니다.)

너비를 데이터에 맞게 조정하려면 데이터를 배열에 저장하고 필요한 너비를 계산한 다음 별표와 함께 이러한 너비를 사용할 수 있습니다 printf "%-*s ", len, data.G-Man이 이 column쇼에 응답했습니다.이렇게 하는 것이 더 쉽습니다.

답변3

다음을 수행하여 열을 정렬할 수 있습니다.

# fcinfo hba-port | awk '
                        BEGIN {printf("HBA_Manufacturer Firmware_Version State\n")
                               printf("---------------- ---------------- -----\n")
                              }
                        /Manufacturer:/ {m=$2}
                        /Firmware Version:/ {F=$3}
                        /State/ {print m, F, $2}' | column -t

그러면 다음과 유사한 출력이 생성됩니다.

HBA_Manufacturer  Firmware_Version  State
----------------  ----------------  -----
Emulex            2.82a4            online
Emulex            2.82a4            online
Emulex            2.82a4            offline
Emulex            2.82a4            offline
Emulex            2.82a4            online
Emulex            2.82a4            online

노트:

  • 열 사이에 더 많은 공간을 원할 경우 끝에 ( 또는 ) 옵션을 사용하여 열 사이에 넣을 문자열을 지정하십시오. 기본값은 공백 2개입니다. 예를 들어 공백 4개를 사용하면 표시된 예제 출력에 더 가까운 결과를 얻을 수 있습니다.--output-separator string-o string… | column -t -o " "
  • 표시된 예제 출력에는 제목 뒤에 연속적인 대시 줄이 있습니다. 위에 표시된 대로 내 명령은 각 제목 아래에 작은 대시 줄만 제공합니다. 일부 데이터가 더 길면 이는 더욱 분명해집니다.

    HBA_Manufacturer         Firmware_Version  State
    ----------------         ----------------  -----
    Emulex                   2.82a4            online
    Emulex                   2.82a4            online
    Some_other_manufacturer  2.82a4            offline
    Emulex                   2.82a4            offline
    Emulex                   2.82a4            online
    Emulex                   2.82a4            online
    

    필요한 경우 이 문제를 해결할 수 있습니다.

답변4

시행착오를 거쳐 탭을 조정해야 할 수도 있지만 일반적으로 -

awk 'BEGIN{printf("HBA_Manufacturer\t\t\tFirmware_Version\t\t\tState\n----------------------------------------\n")} {... printf("%s\t\t\t%s\t\t\t%s\n", m, f,$2) }

관련 정보