как распечатать весь блок, если он содержит определенную строку с командой awk?

Я пытаюсь обработать сетевую информацию от lshw -c network с помощью команды awk

вывод выглядит так: -

*-network:3
   description: Ethernet interface
   product: I350 Gigabit Network Connection
   vendor: Intel Corporation
   physical id: 0.3
   bus info: pci@0000:03:00.3
   logical name: eth1
   version: 01
   serial: xx:xx:xx:xx:xx:xx
   size: 1GB/s
   capacity: 1GB/s
   width: 32 bits
   clock: 33MHz
*-network                 
   description: Ethernet interface
   physical id: 1
   logical name: eth0
   serial: yy:yy:yy:yy:yy:yy
   capabilities: ethernet physical
   configuration: broadcast=yes driver=vif link=yes multicast=yes

Я хочу напечатать это в табличном формате, но только если блок содержит bus info:, здесь только 1-й блок является квалифицированным и будет напечатан в формате

окончательный вывод: -

description   product   vendor   physical id   bus info ...
Ethernet..    I350 G..  Intel..  0.3           pci@0000:03:00.3

мои лучшие усилия: -

    lshw -c network | 
    awk -v FS=: 
    $0 ~ /*-network.*/ {
        v1 = NR; 
        v2 = ""; 
        v3 = 0
    } 

    NR > v1 && v3 == 0 {
        v2 = v2"@"$3
        } 

    $1 ~ /bus info.*/ {
        v3 = 1
        }  

    v3 == 1 {
        split(v2, ar, "@"); 
        for (t in ar) { print t}; 
        print $1
    }

без везения


person rahul Kushwaha    schedule 12.03.2020    source источник


Ответы (2)


Всякий раз, когда у вас есть входная дата с сопоставлениями тега (имя) = значение, лучше сначала создать массив, содержащий эти сопоставления (tag2val[] ниже), а затем вы можете анализировать любые комбинации полей, присутствующих и/или имеющих определенные значения, которые вам нравятся, и печатать все, что угодно поля, которые вам нравятся, в любом порядке. Например:

$ cat tst.awk
BEGIN { OFS="\t" }
/^[*]/ { prt() }
{
    gsub(/^[[:space:]]+|[[:space:]]+$/,"")
    gsub(OFS," ")
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+:[[:space:]]*/,"",val)
    tag2val[tag] = val
}
END { prt() }

function prt(   flds, numFlds, fldNr) {
    numFlds = split("description,product,vendor,physical id,bus info",flds,/,/)
    if ( "bus info" in tag2val ) {
        if ( !doneHdr++ ) {
            for (fldNr=1; fldNr<=numFlds; fldNr++) {
                tag = flds[fldNr]
                printf "%s%s", tag, (fldNr<numFlds ? OFS : ORS)
            }
        }
        for (fldNr=1; fldNr<=numFlds; fldNr++) {
            tag = flds[fldNr]
            val = tag2val[tag]
            printf "%s%s", val, (fldNr<numFlds ? OFS : ORS)
        }
    }
    delete tag2val
}

.

$ awk -f tst.awk file | column -s$'\t' -t
description         product                          vendor             physical id  bus info
Ethernet interface  I350 Gigabit Network Connection  Intel Corporation  0.3          pci@0000:03:00.3
person Ed Morton    schedule 12.03.2020

Если кому интересно:

Эта команда работает: -

lshw -c network | 
awk -v out='description\tproduct\tvendor\tphysical id\tbus info\tlogical name\tversion\tserial\twidth\tclock\tcapabilities\tconfiguration\tresources' 
    -v v1=0 -F ': ' 
' $0 ~ /*-network.*/ {
    if (v1 == 1) {print out;} 
    out = ""; 
    v1=0 
} 
$1 ~ /bus info.*/ { 
    v1 = 1
    } 
{ 
    out = out"\t"$2 
} 
END{ 
    if (v1 == 1) print out 
}'
person rahul Kushwaha    schedule 12.03.2020
comment
Это не будет печатать последнюю запись во входных данных, если она содержит bus info, и будет печатать только часть данных, если/когда она содержит : (представьте себе название продукта, например Ethernet: version 2), и будет печатать все блоки до включительно тот, который содержит bus info, а не только тот, который содержит его. - person Ed Morton; 13.03.2020
comment
Думаю, сейчас напечатают. - person rahul Kushwaha; 13.03.2020
comment
перечитайте последнюю часть моего комментария и подумайте, где вы устанавливаете v1=0. - person Ed Morton; 13.03.2020
comment
Я обновил и проверил эту команду, если есть какие-либо проблемы, плз, приведите пример - person rahul Kushwaha; 14.03.2020
comment
Единственная оставшаяся проблема заключается в том, что он будет печатать только часть данных, если/когда он содержит: (представьте себе имя продукта, например Ethernet: version 2). Посмотрите, как я использовал tag = val = $0; sub(/[[:space:]]*:.*/,"",tag); sub(/[^:]+:[[:space:]]*/,"",val) вместо использования полей, чтобы сделать его надежным, разбивая строку на первом :, а не на каждом : . - person Ed Morton; 14.03.2020