空の場合でも、コマンド出力から列を抽出します。

空の場合でも、コマンド出力から列を抽出します。

コマンド出力から2番目の列を抽出しようとしています。

たとえば、

$ sudo /usr/sbin/pvs
  PV         VG       Fmt  Attr PSize   PFree
  /dev/sdc1  vgswap   lvm2 a--   16.00g      0
  /dev/sdc2  rootvg   lvm2 a--   48.00g   2.70g
  /dev/sde            lvm2 ---   32.00g  32.00g
  /dev/sdf            lvm2 ---   32.00g  32.00g

しかし、問題は、一部のディスクがVGに関連付けられていないため、出力の抽出中にVG名が空であることです。

$ sudo /usr/sbin/pvs | awk '{print $2}'
VG
vgswap
rootvg
lvm2
lvm2

このように抽出したいです(空の場合は空にしてください)

vgswap
rootvg

答え1

ユーザー専用のデフォルト形式ではなく、後処理用に設計された出力形式を使用します。

$ sudo pvs --reportformat json_std | jq -r '.report[].pv[].vg_name'
vgswap
rootvg


または、pvs希望の形式で希望の値を取得するように依頼してください。

$ sudo pvs --no-headings --config 'log{prefix=""}' -o vg_name
vgswap
rootvg



ソートとインデントを無効にし、区切り文字を変更することで、デフォルトの出力形式を後処理するのが簡単になります。

sudo pvs --config $'report{aligned=0 separator="\t"}log{prefix=""}'

値に改行やタブが含まれていない限り、それを単純なTSVにし、次のように後処理できます。

列には常にヘッダーvg_nameがあるとしますVG

mlr --tsvlite --headerless-csv-output  cut -f VG

または:

awk 'NR==1{for (i = i; i <= NF; i++) h[$i]=i; next}
     {print $ h["VG"]}'

あるいは、そのvg_name列が常に2番目の列であると仮定します。

awk -F'\t' 'NR > 1 {print $2}'

出力形式を変更せずに、デバイス名に改行文字やその他の制御文字またはマルチバイト文字が含まれていないと仮定し、VG名にスペースを含めることができないという事実に基づいて、最初のVGヘッダー行で文字列のオフセットを変更できます。 。その後の行でその値を見つける場所を知るために記録されました。

sudo pvs | awk '
  NR == 1 {offset = index($0, "VG"); next}
  {$0 = substr($0, offset); sub(/ .*/, ""); print}'

答え2

awkを使用してください。

$ cat file | awk 'NR==1{n=NF; next} {print (NF<n ? "" : $2)}'
vgswap
rootvg


これは単に最初の行のフィールド数を出力するように設定しn、そのフィールド数があれば$ 2を印刷し、それ以外の場合は行の残りの部分に空の文字列を印刷します。

GNU awkを使用することもできますFIELDWIDTHS固定幅フィールドあなたのコメントから:

$ cat file | awk -v FIELDWIDTHS='13 9 *' 'NR>1{print $2}'
vgswap
rootvg


システムのに置き換えてくださいcat filesudo /usr/sbin/pvs

関連情報