Como ativar um espaço em branco para se tornar uma entrada de loop for?

Como ativar um espaço em branco para se tornar uma entrada de loop for?

Aqui está um exemplo de texto. (Seu nome é 20210622_090009)

nvmeSerial      Endpoint        nvmeSpeed           nvmeWidth
================================================================================
nvme0n1         c7:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme1n1         c8:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme2n1         c9:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme3n1         ca:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme4n1         85:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme5n1         86:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme6n1         87:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme7n1         88:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme8n1         41:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme9n1         42:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme10n1        43:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme11n1        44:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme12n1        45:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme13n1        46:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme14n1        47:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme15n1        48:00.0                             Width x2 (downgraded)
nvme16n1        01:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme17n1        02:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme18n1        03:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme19n1        04:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme20n1        05:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme21n1        06:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme22n1        07:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme23n1        08:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme24n1        09:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme25n1        0a:00.0     Speed 32GT/s (ok)       Width x2 (downgraded)

Aqui está o roteiro:

#! /bin/bash
IFS_old="$IFS"
IFS=$'\n'

for line in $(cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}' )
do
    echo "$line" 
done
IFS="$IFS_old"
exit 0

A saída do script é

8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s

Quero pegar o nvmeSpeed(Ex:8GT/s) quer a velocidade tenha o número ou não.

Como você pode ver, nvmeSpeed ​​in nvme15n1é um espaço em branco.

E a saída não aparece.

Minha pergunta é:

Como ativar um espaço em branco para se tornar uma entrada de loop for?

Responder1

awksozinho pode fazer tudo isso. Você não precisa de um wrapper de script de shell, certamente não precisa de nada tão barroco quanto cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}') e deve evitar usar um loop while-read do shell (ou um loop for sobre a saída de uma linguagem como awk ou perl) onde quer que possível (verPor que usar um loop de shell para processar texto é considerado uma prática inadequada?por motivos).

Regra prática: se você estiver pensando "Eu quero iterar sobre a saída do awk", você deve mudar seu pensamento para "Eu quase certamente deveria fazer isso apenas com o awk", ou um wrapper de shell que configure o redirecionamento de entrada e saída para o awk para fazer o trabalho de processamento em massa. O mesmo para perl e a maioria dos outros idiomas. Qualquer outra linguagem fará o trabalho de processamento melhor que o shell, e você só tornará seu trabalho mais difícil tentando fazê-lo com o shell.

De qualquer forma, o script a seguir imprime a coluna 4 se houver exatamente 8 colunas ( NF == 8). Se houver menos de 8 colunas ( NF < 8), será impressa uma linha em branco. Em ambos os casos, ele ignora as duas linhas de cabeçalho no início de cada arquivo de entrada (ele pode lidar com um ou mais argumentos de nome de arquivo. FNR < 3 {next}No awk, NR é o número total de linhas lidas, enquanto FNR é o número da linha doatualarquivo).

$ awk 'FNR < 3 {next}; NF == 8 {print $4}; NF < 8 {print ""}' 20210622_090009.txt  
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s

8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s

Responder2

Parece que você tem campos de largura fixa, usando GNU awk para FIELDWIDTHS e gensub():

$ awk -v FIELDWIDTHS='16 12 24 *' '
    NR>2 {
        gsub(/^ *| *$/,"",$3)
        print gensub(/.* ([^ ]+) .*/,"\\1",1,$3)
    }
' file
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s

8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
8GT/s
32GT/s

O texto acima primeiro identifica o conteúdo de cada campo pela largura de cada campo:

$ cat file
nvmeSerial      Endpoint        nvmeSpeed           nvmeWidth
================================================================================
nvme0n1         c7:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme1n1         c8:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
nvme15n1        48:00.0                             Width x2 (downgraded)
nvme25n1        0a:00.0     Speed 32GT/s (ok)       Width x2 (downgraded)

$ cat tst.awk
BEGIN { FIELDWIDTHS="16 12 24 *" }
NR != 2 {
    print
    for (i=1; i<=NF; i++) {
        gsub(/^ *| *$/,"",$i)
        print "\t" i, "<" $i ">"
    }
    print "-----"
}

$ awk -f tst.awk file
nvmeSerial      Endpoint        nvmeSpeed           nvmeWidth
        1 <nvmeSerial>
        2 <Endpoint>
        3 <nvmeSpeed>
        4 <nvmeWidth>
-----
nvme0n1         c7:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
        1 <nvme0n1>
        2 <c7:00.0>
        3 <Speed 8GT/s (ok)>
        4 <Width x2 (downgraded)>
-----
nvme1n1         c8:00.0     Speed 8GT/s (ok)        Width x2 (downgraded)
        1 <nvme1n1>
        2 <c8:00.0>
        3 <Speed 8GT/s (ok)>
        4 <Width x2 (downgraded)>
-----
nvme15n1        48:00.0                             Width x2 (downgraded)
        1 <nvme15n1>
        2 <48:00.0>
        3 <>
        4 <Width x2 (downgraded)>
-----
nvme25n1        0a:00.0     Speed 32GT/s (ok)       Width x2 (downgraded)
        1 <nvme25n1>
        2 <0a:00.0>
        3 <Speed 32GT/s (ok)>
        4 <Width x2 (downgraded)>
-----

e então é trivial selecionar a parte do terceiro campo que você deseja imprimir. por exemplo, usando gensub()como eu fiz. O procedimento acima funcionará independentemente de quais campos estão faltando em qualquer linha, quantas palavras estão em qualquer campo, etc.

Responder3

Outro método assumindo campos de largura fixa (extrai apenas um dos campos, e assume que ele sempre começa com os 6 caracteres "Velocidade" se não estiver vazio):

cut -c35-52 file | sed '1,2d;s/ .*//'

Ou combine "Velocidade":

awk -F ' Speed +' 'NR>2 {sub(/ .*/,"",$2); print $2}' file
sed -E '1,2d;s/.* Speed +([^ ]+).*/\1/;t;c\\' file
perl -nE 'say m{\sSpeed\s+(\S+)} if $.>2' file

Responder4

 awk 'NR>2{if($4 ~ /^[0-9].*GT/){print $1" =======>" $4}else{if($4 !~ /^[0-9].*GT/){print $1"==================== doesnt contain speed==========================="}}}' filename

saída

nvme0n1 =======>8GT/s
nvme1n1 =======>8GT/s
nvme2n1 =======>8GT/s
nvme3n1 =======>8GT/s
nvme4n1 =======>8GT/s
nvme5n1 =======>8GT/s
nvme6n1 =======>8GT/s
nvme7n1 =======>8GT/s
nvme8n1 =======>8GT/s
nvme9n1 =======>8GT/s
nvme10n1 =======>8GT/s
nvme11n1 =======>8GT/s
nvme12n1 =======>8GT/s
nvme13n1 =======>8GT/s
nvme14n1 =======>8GT/s
nvme15n1==================== doesnt contain speed===========================
nvme16n1 =======>8GT/s
nvme17n1 =======>8GT/s
nvme18n1 =======>8GT/s
nvme19n1 =======>8GT/s
nvme20n1 =======>8GT/s
nvme21n1 =======>8GT/s
nvme22n1 =======>8GT/s
nvme23n1 =======>8GT/s
nvme24n1 =======>8GT/s
nvme25n1 =======>32GT/s

informação relacionada