如何將 awk 的空格變成 for 迴圈輸入?

如何將 awk 的空格變成 for 迴圈輸入?

這是一個範例文字。

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)

這是腳本:

#! /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

腳本輸出是

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

我想取得 nvmeSpeed(Ex:8GT/s) 無論速度是否有數字。

如您所見,nvmeSpeed innvme15n1是一個空格。

且輸出不顯示。

我的問題是:

如何將 awk 空格變成 for 迴圈輸入?

答案1

awk獨自一人就可以完成這一切。您不需要 shell 腳本包裝器,當然也不需要像cat 20210622_090009.txt | tail -n 26 | cut -f 5 | awk '{print $2}') 這樣巴洛克式的東西,並且您應該避免在任何地方使用 shell while-read 循環(或對 awk 或 perl 等語言的輸出進行 for 循環)可能(參見為什麼使用 shell 循環處理文字被認為是不好的做法?原因)。

經驗法則:如果您發現自己在想“我想迭代awk 的輸出”,您應該將您的想法改為“我幾乎肯定應該只使用awk 來完成此操作”,或者為awk 設定輸入和輸出重定向的shell 包裝器進行批量加工工作。 Perl 和大多數其他語言也是如此。任何其他語言都會比 shell 更好地完成處理工作,並且嘗試使用 shell 只會讓您的工作變得更加困難。

無論如何,如果正好有 8 列 ( NF == 8),則以下腳本將列印第 4 列。如果少於 8 列 ( NF < 8),則列印空白行。在這兩種情況下,它都會忽略每個輸入檔案開頭的兩個標題行(它可以處理一個或多個檔案名稱參數。 FNR < 3 {next}在awk 中,NR 是讀取的總行數,而FNR 是讀取的行數)目前的文件)。

$ 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

答案2

看起來您有固定寬度的字段,因此,使用 GNU awk 作為 FIELDWIDTHS 和 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

上面首先透過每個欄位的寬度來標識每個欄位的內容:

$ 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)>
-----

然後選擇要列印的第三個欄位的部分就很簡單了。例如gensub()像我一樣使用。無論任何行中缺少哪些欄位、任何欄位中有多少個單字等,上述內容都將起作用。

答案3

另一種假設固定寬度字段的方法(僅提取其中一個字段,並假設它始終以 6 個字元“Speed”開頭(如果它不為空):

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

或匹配“速度”:

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

答案4

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

輸出

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

相關內容