awkは無効な列のフィールドを印刷します。

awkは無効な列のフィールドを印刷します。

次のコマンドを実行すると、以下のように列リストが出力されます。

# rancher clusters
CURRENT   ID        STATE     NAME                           PROVIDER  
*         abcd      active    test-cluster                   Imported
          efgh      active    prod-cluster                   Imported
          xyzd      active    dev-cluster                    Imported

NAME列を印刷しようとすると、test-clusterは結果に返されません。

# rancher clusters | awk '{print $3}'
STATE
active
prod-cluster
dev-cluster

印刷されたNAME列に表示されているSTATE列の一部を表示できます。

4 番目の列を印刷すると、テストクラスターが NAME とともに返されます。

# rancher clusters | awk '{print $4}'
NAME
test-cluster
Imported
Imported

awkが印刷された正確な列の値を返さないのはなぜですか?ある列の値が別の列に返されるのはなぜですか?私の期待は、3ドルを印刷すると、4番目の列(名前)のすべての結果が得られることです。

答え1

あなたはいGet $3- しかし、デフォルトでは、awkはレコードをフィールドに分割するときの先頭と末尾のスペースを無視します。

フィールド区切り文字を明示的に設定して、前のスペースを空のフィールドとして扱うように強制できる必要があります。

$ cat clusters | awk -F'[ \t]+' '{print $3}'
STATE
active
active
active

しかし、

$ cat clusters | awk '{print $3}'
STATE
active
prod-cluster
dev-cluster

答え2

awkは区切り文字に基づいて文字列を分割します(デフォルトは1つ以上のスペース、つまりタブまたはスペース)。より明確にするために、ここにあなたのデータがあります。データは以下で提供されます。|

CURRENT|ID|STATE|NAME|PROVIDER
*|abcd|active|test-cluster|Imported
efgh|active|prod-cluster|Imported
xyzd|active|dev-cluster|Imported

上記のように、最初の行は$1is CURRENT$2isIDなどです。 2行目$1はis *$2isabcdなどです。ただし、3行目はID列に対応しています$1efghCURRENT列にはスペース以外には何もないため、awkはこれを無視して$33行と4行のNAMEを表示します。

あなたがしなければならないのは、最初の列をawkに送信する前に削除することだけです。次のコマンドを使用できます。

rancher clusters | cut -b 8- | awk '{ print $3 }'

cut上記のパイプラインのコマンドは、各行の最初の7バイトを削除し、残りはSTDOUTに印刷します。これにより、awk各行の列数が異なる場合でも混乱は発生しません。

答え3

デフォルトでは、awk は先行スペースと末尾のスペースを無視し、連続したスペースシーケンスに基づいてレコードをフィールドに区切ります。最初の「フィールド」は時々空であり、awkは存在しません。これを考えると、NAME列を印刷する方法はいくつかあります。最も簡単な方法は、レコードの先頭ではなく最後からフィールド数を数えることです。

$ awk '{print $NF}' file
PROVIDER
Imported
Imported
Imported
$
$ awk '{print $(NF-1)}' file
NAME
test-cluster
prod-cluster
dev-cluster
$
$ awk '{print $(NF-2)}' file
STATE
active
active
active
$
$ awk '{print $(NF-3)}' file
ID
abcd
efgh
xyzd
$
$ awk '{print (NF>4 ? $(NF-4) : "")}' file
CURRENT
*


$

$(NF-4)NFが4のときに印刷されないように、最後の項目に対していくつかの計算を実行する必要があります$0。 4をハードコーディングする代わりに、ヘッダー行のフィールド数を数えることで予想されるフィールド数を計算できます。

$ awk 'NR==1{max=NF-1} {print (NF>max ? $(NF-max) : "")}' file
CURRENT
*


$

答え4

問題は、rancherコマンド出力に1行に5つのフィールドがある場合もあり、4つのフィールドがある場合もあることです。

NF次のawk 1行ステートメントは、指定された入力行のフィールド数に基づいて正しいフィールドを印刷します(awkの組み込み変数を使用)。

$ awk 'NF==5 {print $4}; NF==4 {print $3}' clusters.txt
NAME
test-cluster
prod-cluster
dev-cluster

または、空の行がないと確信している場合は、次のように使用できます。

$ awk '{print $(NF-1)}' clusters.txt 
NAME
test-cluster
prod-cluster
dev-cluster

空行があると、次のエラーメッセージが表示されます。

awk: cmd. line:1: (FILENAME=clusters.txt FNR=5) fatal: attempt to access field -1

これは次の方法で回避できます。

awk 'NF>=1 {print $(NF-1)}' clusters.txt 

関連情報