シェル結果を列のExcelファイルに変換

シェル結果を列のExcelファイルに変換

次の結果を提供するシェルスクリプトを実行しており、結果をExcelの他の列(ホスト、状態、有効期限、日)に保存したいと思います。 Excelにどのように変換しますか?

Host                                            Status       Expires      Days
----------------------------------------------- ------------ ------------ ----
FILE:certs/dnscert.crt                          Valid        Aug  4, 2021  359

答え1

サンプル入力を変更します。

$ cat input
Host                                            Status       Expires      Days
----------------------------------------------- ------------ ------------ ----
FILE:certs/dnscert1.crt                         Valid        Aug  1, 2020  7
FILE:certs/dnscert2.crt                         Invalid      Aug  4, 2021  359
FILE:certs/dnscert3.crt                         Valid        Aug  4, 2021  359

次に、次のawkコマンドを適用すると、次のような結果が得られます。

$ awk 'NR > 2 { print $1 "," $2 ",\"" $3, $4, $5 "\"," $6}' input
FILE:certs/dnscert1.crt,Valid,"Aug 1, 2020",7
FILE:certs/dnscert2.crt,Invalid,"Aug 4, 2021",359
FILE:certs/dnscert3.crt,Valid,"Aug 4, 2021",359

日付フィールドは、常に月、日、年の3つのトークンであると仮定します。

NR > 2最初の2行(ヘッダーと区切り記号)をスキップします。残りは、間にカンマ区切りのフィールドを印刷し、日付フィールドを引用するときに注意してください。

答え2

シェルスクリプトがデータ配置のためのスペースを提供すると仮定すると、awkを使用してタブ区切り形式に変換できます。 Excelはタブ区切りのファイルを開き(形式の不一致について文句を言うことができます)、必要に応じてxlsxとして保存できるようにします。

$my_script | awk -v OFS='\t' '{$1=$1}1' > myexcel.xls

OFSを強制的に適用してから印刷するトリックを使用します。またはあまり不思議ではない:

$my_script | '{print $1 "\t" $2 "\t" $3 "\t" $4}' > myexcel.xls

「実際の」xlsxファイル(XMLの圧縮ディレクトリ)を生成できるお気に入りのスクリプト言語用のモジュールがありますが、これはもう少し複雑です。ユーザーがクリックしてExcelで開くことができる項目のみが必要な場合は、xls拡張子を使用してタブ区切りにすることをお勧めします。

答え3

フィールド自体にも日付フィールドなどのスペースが含まれているため、他の戦略を考案する必要があります。

ヘッダーを使用して各フィールドのフィールド幅を取得し(フィールド名にスペースがないと仮定)、awkのFIELDWIDTHS組み込み変数に挿入して入力ファイルを2番目に渡します。

$ fw=$(< file \
   awk -v FPAT='[^[:space:]]+([[:space:]]+|$)' '  NR>1{exit}
{for (i=1; i<=NF; i++) $i=length($i)}1')

$ awk \
  -v q=\" -v OFS=,     \
  -v FIELDWIDTHS="$fw" \
'
function trim(a,  l, t) {
  l = "^[[:space:]]+"
  t = "[[:space:]]+$" 
  re = l "|" t
  gsub(re, "", a)
  return a
}
function quote(a,  r, nondigit) {
  r = "[^[:digit:]]"
  nondigit = a ~ r
  return nondigit ? q a q : a
}
NR==2{next} 
{
  for (i=1; i<=NF; i++) {
    t = $i
    gsub(/"/, "\\&", t)
    t = trim(t)
    $i = quote(t)
  }
}1' file

"Host","Status","Expires","Days"
"FILE:certs/dnscert.crt","Valid","Aug  4, 2021",359

関連情報