awk에서 getline의 이상한 동작 |

awk에서 getline의 이상한 동작 |

문제: 명령 변수 값은 li12[q]자체 실제 내용으로 참조될 수 없습니다.

증상: 명령 변수 value 를 실제로 인용하면 li12[q]fatal: |리디렉션에 사용된 표현식에 빈 문자열 값이 있습니다.

노트:

  1. 그러나 명령 변수에는 이전 k5 변수와 동일한 자체 값이 있습니다 li12[q]!getline
  2. li12[q]명령 변수 이름 자체를 인용할 수 있으므로 해당 구문과 구조에는 문제가 없습니다.
# 
# 
# lspci -v|grep -Ei "fib|scsi|raid|sas|net|ide|ata"|grep -i ^[0-9]|awk  '{kin1[NR]=$1; prt[NR]="";for(ik=2;ik<=NF;ik++){prt[NR]=prt[NR]$ik" "}}END\
{while("ls -l /sys/class|grep -Ei \"scsi|sas|fc|net|ide|ata\"|grep -Eiv \"disk|tape|device|gen\""|getline){li11[++h1]=$9}; for(i=1;i<=NR;i++)\
{for(s=1;s<=h1;s++){h2=0;d3="(find /sys/class/"li11[s]" -type l -exec bash -c '\''echo s `ls -l {}`'\'' \\;|grep -i devices|grep -Ei \""kin1[i]"(/|$)\")\
2>/dev/null"; while(d3|getline){k5=li12[++h2]=$10$11$12; k6=h2}; for(q=1;q<=h2;q++){if(li12[q] ~/[a-zA-Z]/){ while("echo -e \"li12[q]\""|getline k7); k2=k7; k3=$1;\
if( q == h2 ){s=h1+1}; if(q>1){kin1[i]=prt[i]=""};printf " %-16s%-6s%-16s%-16s%-100s%-16s\n",kin1[i],k6,k5,k3,prt[i],k2}}}}}'
 03:00.0         1     /sys/class/scsi_host/host0/device->../../../devices/pci0000:00/0000:00:02.2/0000:03:00.0/host0s RAID bus controller: Hewlett-Packard Company Smart Array Gen8 Controllers (rev 01)                  li12[q]         
 04:00.0         1     /sys/class/net/eth0/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.0s Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (be3) (rev 01)                          li12[q]         
 04:00.1         1     /sys/class/net/eth1/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.1s Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (be3) (rev 01)                          li12[q]         
 04:00.2         1     /sys/class/iscsi_host/host3/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.2/host3s Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01)          li12[q]         
 04:00.3         1     /sys/class/iscsi_host/host4/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.3/host4s Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01)          li12[q]         
 05:00.0         1     /sys/class/fc_host/host1/device->../../../devices/pci0000:00/0000:00:03.0/0000:05:00.0/host1s Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)             li12[q]         
 05:00.1         1     /sys/class/fc_host/host2/device->../../../devices/pci0000:00/0000:00:03.0/0000:05:00.1/host2s Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)             li12[q]         
# 
# 
# 
# lspci -v|grep -Ei "fib|scsi|raid|sas|net|ide|ata"|grep -i ^[0-9]|awk  '{kin1[NR]=$1; prt[NR]="";for(ik=2;ik<=NF;ik++){prt[NR]=prt[NR]$ik" "}}END\         
{while("ls -l /sys/class|grep -Ei \"scsi|sas|fc|net|ide|ata\"|grep -Eiv \"disk|tape|device|gen\""|getline){li11[++h1]=$9}; for(i=1;i<=NR;i++)\
{for(s=1;s<=h1;s++){h2=0;d3="(find /sys/class/"li11[s]" -type l -exec bash -c '\''echo s `ls -l {}`'\'' \\;|grep -i devices|grep -Ei \""kin1[i]"(/|$)\")\
2>/dev/null"; while(d3|getline){k5=li12[++h2]=$10$11$12; k6=h2}; for(q=1;q<=h2;q++){if(li12[q] ~/[a-zA-Z]/){ while("echo -e "li12[q]""|getline k7); k2=k7; k3=$1; \
if( q == h2 ){s=h1+1}; if(q>1){kin1[i]=prt[i]=""};printf " %-16s%-6s%-16s%-16s%-100s%-16s\n",kin1[i],k6,k5,k3,prt[i],k2}}}}}'
awk: cmd. line:3: (FILENAME=- FNR=7) fatal: expression for `|' redirection has null string value
# 
#

편집 다음은 @glennjackman이 제공한 더 명확하게 형식화된 위의 코드입니다.

lspci -v \
| grep -Ei "fib|scsi|raid|sas|net|ide|ata" \
| grep -i ^[0-9] \
| awk  '
    {
        kin1[NR] = $1
        prt[NR] = ""
        for (ik = 2; ik <= NF; ik++) {prt[NR] = prt[NR] $ik " "}
    }
    END {
        while ("ls -l /sys/class | grep -Ei \"scsi|sas|fc|net|ide|ata\" | grep -Eiv \"disk|tape|device|gen\"" | getline) {
            li11[++h1] = $9
        }
        for (i = 1; i <= NR;i++) {
            for (s = 1; s <= h1;s++) {
                h2 = 0
                d3 = "(find /sys/class/"li11[s]" -type l -exec bash -c '\''echo s `ls -l {}`'\'' \\; | grep -i devices | grep -Ei \""kin1[i]"(/|$)\") 2>/dev/null"
                while (d3 | getline){
                    k5 = li12[++h2] = $10 $11 $12
                    k6 = h2
                }
                for (q = 1; q <= h2;q++){
                    if (li12[q] ~/[a-zA-Z]/) {
                        while ("echo -e "li12[q]"" | getline k7)
                            k2 = k7
                        k3 = $1
                        if (q == h2) {s = h1+1}
                        if (q > 1) {kin1[i] = prt[i] = ""}
                        printf " %-16s%-6s%-16s%-16s%-100s%-16s\n", kin1[i], k6, k5, k3, prt[i], k2
                    }
                }
            }
        }
    }
'

이제 RHEL 6.4 시스템에서 위와 동일한 awk 스크립트를 사용하면 다른 실패 결과/진행이 제공됩니다.
참고: 동일한 빈 문자열 값에 대해 이전에 실패한 모든 결과는 RHEL 5.8 시스템에서만 작동했습니다.
sh: ../../../devices/pci0000:00/0000:00:02.2/0000:03:00.0/host0: No such file or directory
 03:00.0         1     /sys/class/scsi_host/host0/device->../../../devices/pci0000:00/0000:00:02.2/0000:03:00.0/host0s               RAID bus controller: Hewlett-Packard Company Smart Array Gen8 Controllers (rev 01)                                  
sh: ../../../devices/pci0000:00/0000:00:02.0/0000:04:00.0: No such file or directory
 04:00.0         1     /sys/class/net/eth0/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.0s               Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (be3) (rev 01)                                          
sh: ../../../devices/pci0000:00/0000:00:02.0/0000:04:00.1: No such file or directory
 04:00.1         1     /sys/class/net/eth1/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.1s               Ethernet controller: Emulex Corporation OneConnect 10Gb NIC (be3) (rev 01)                                          
sh: ../../../devices/pci0000:00/0000:00:02.0/0000:04:00.2/host3: No such file or directory
 04:00.2         1     /sys/class/iscsi_host/host3/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.2/host3s               Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01)                          
sh: ../../../devices/pci0000:00/0000:00:02.0/0000:04:00.3/host4: No such file or directory
 04:00.3         1     /sys/class/iscsi_host/host4/device->../../../devices/pci0000:00/0000:00:02.0/0000:04:00.3/host4s               Mass storage controller: Emulex Corporation OneConnect 10Gb iSCSI Initiator (be3) (rev 01)                          
sh: ../../../devices/pci0000:00/0000:00:03.0/0000:05:00.0/host1: No such file or directory
 05:00.0         1     /sys/class/fc_host/host1/device->../../../devices/pci0000:00/0000:00:03.0/0000:05:00.0/host1s               Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)                             
sh: ../../../devices/pci0000:00/0000:00:03.0/0000:05:00.1/host2: No such file or directory
 05:00.1         1     /sys/class/fc_host/host2/device->../../../devices/pci0000:00/0000:00:03.0/0000:05:00.1/host2s               Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)  

답변1

공백은 무료이므로 일부를 사용해야 합니다.

이게 당신이 하는 일인가요?

lspci -v \
| grep -Ei "fib|scsi|raid|sas|net|ide|ata" \
| grep -i ^[0-9] \
| awk  '
    {
        kin1[NR] = $1
        prt[NR] = ""
        for (ik = 2; ik <= NF; ik++) {prt[NR] = prt[NR] $ik " "}
    }
    END {
        while ("ls -l /sys/class | grep -Ei \"scsi|sas|fc|net|ide|ata\" | grep -Eiv \"disk|tape|device|gen\"" | getline) {
            li11[++h1] = $9
        }
        for (i = 1; i <= NR;i++) {
            for (s = 1; s <= h1;s++) {
                h2 = 0
                d3 = "(find /sys/class/"li11[s]" -type l -exec bash -c '\''echo s `ls -l {}`'\'' \\; | grep -i devices | grep -Ei \""kin1[i]"(/|$)\") 2>/dev/null"
                while (d3 | getline){
                    k5 = li12[++h2] = $10 $11 $12
                    k6 = h2
                }
                for (q = 1; q <= h2;q++){
                    if (li12[q] ~/[a-zA-Z]/) {
                        while ("echo -e "li12[q]"" | getline k7)
                            k2 = k7
                        k3 = $1
                        if (q == h2) {s = h1+1}
                        if (q > 1) {kin1[i] = prt[i] = ""}
                        printf " %-16s%-6s%-16s%-16s%-100s%-16s\n", kin1[i], k6, k5, k3, prt[i], k2
                    }
                }
            }
        }
    }
'

답변2

@rowboat 귀하의 훌륭한 답변에 진심으로 감사드립니다. 이 답변을 테스트한 결과 성공적으로 작동했습니다!

다음 명령문으로 바꾸십시오
.

while ("echo -e "li12[q]"" | getline k7)

도착하다:

while (("echo -e "li12[q]"") | getline k7)

관련 정보