bash - "テーブル"の値を配列の文字列に分割します。

bash - "テーブル"の値を配列の文字列に分割します。

編集:申し訳ありません。私が主張した結果は間違っています。以前に考えたよりも多くのスペースがあります(これらのスペースを削除するために出力をhtmlファイルに保存したときに問題が発生しました)。実際の出力は次のとおりです。

user@Debian:~$ sudo smartctl -l selftest /dev/sda | grep -e "#"
# 1  Short offline       Completed without error       00%      7264         -
# 2  Short offline       Completed without error       00%      7240         -
# 3  Short offline       Completed without error       00%      7219         -
# 4  Short offline       Completed without error       00%      7192         -
# 5  Short offline       Completed without error       00%      7168         -
# 6  Short offline       Completed without error       00%      7144         -
# 7  Extended offline    Completed without error       00%      7125         -
# 8  Short offline       Completed without error       00%      7096         -
# 9  Short offline       Completed without error       00%      7072         -
#10  Short offline       Completed without error       00%      7049         -
#11  Short offline       Completed without error       00%      7004         -

私はLinux/bashに初めて触れたので、正しい用語を使用しているかどうかはわかりません。

とにかく、私はSMARTエラーがあるかどうかを検出して知らせるためにSmartmontoolsを使用しています。私は望む方法で動作しましたが、HDDに関する毎日の統計を取得したかったので、smartmontoolsと一時的な、SMART値、使用されたHDDスペースなどの他の興味深いアイテムから情報を収集するスクリプトを自分で作成しました。おそらくこのようなことをする最善の方法ではありません。しかし、私はこのことを楽しみながら学び続けています。

私が送った電子メールは、テーブルを作成し、肯定的/否定的な結果にフォントの色(緑色/赤色)を追加するためにHTML形式で書かれました。しかし、セルフテストを表示するためのテーブルを作成しようとすると、いくつかの問題が発生します。

私が使用するコマンドは次のとおりです。 (sudo smartctl -l selftest $HDD | grep '#' >> $SMARTFILEループでは、$ HDDは私のシステムのすべてのHDDで、$ SMARTFILEは私が保存するhtmlファイルです。

このコマンドの出力は次のとおりです。

#1簡単なオフラインがエラーなしで完了しました。 00% 7264 -

#2 エラーなしで簡単なオフライン完了 00% 7240 -

など。次のコードを使用してドライブのシリアル番号を取得します。

HDDinfo="$(sudo smartctl --info $HDD | grep -e 'Serial Number')"
IFS=':' read -r -a array <<< "$HDDinfo"

sudo smartctl --info $HDD | grep -e 'Serial Number'正常に出力されるため

所蔵番号 : WD-RESTOFS/N123

しかし、これをテーブルに入れるには、文字列を「:」文字で区切り、次のような配列を得ました。

シリアル番号、WD-RESTOFS/N123

しかし、私が得ている出力にはsudo smartctl -l selftest $HDD | grep '#' >> $SMARTFILEそれらを分離する確実な方法はなく、以前に行った方法は機能しません。なぜなら、私が望む文字列にスペースがあり、次のように区切ることができないからです。空白文字。

TL;DR、次のコマンドがあり、sudo smartctl -l selftest /dev/sda | grep '#' >> $SMARTFILEその出力は次のようになります。

#1簡単なオフラインがエラーなしで完了しました。 00% 7264 -

#2 エラーなしで簡単なオフライン完了 00% 7240 -

次のように個別に保存するための配列(または同様の配列)を作成したいと思います。

#1、一時的にオフライン、エラーなしで完了、00%、7264、 -

これにより、HTMLテーブルに簡単に配置できます。これは可能ですか?エラーが発生すると、次のように表示されることがあります。

#1ショートオフライン完了:読み取りに失敗しました20%717 555027747

不明な場合や追加情報が必要な場合はお知らせください。

答え1

上記の(小さい)メッセージサンプルでは、smartctl​​その部分は本質的に「<space> <小文字を除くすべてのもの」(行の先頭の「#nnn」フィールドを除く)で区切られているように見えます。

sed部品を取り外すのに役立ちます。

$ smartctl_output="\                                           
# 1 Short offline Completed without error 00% 7264 -
# 2 Short offline Completed without error 00% 7240 -
# 1 Short offline Completed: read failure 20% 717 555027747"

$ csv="$( sed 's/ //; s/ \([^[:lower:]]\)/,\1/g' <<< "$smartctl_output" )"

$ echo "$csv"
#1,Short offline,Completed without error,00%,7264,-
#2,Short offline,Completed without error,00%,7240,-
#1,Short offline,Completed: read failure,20%,717,555027747

これが必要な場合は、HDDinfoと同様にアレイを埋めることができます。

【書き直す】

sed分割を行う部分の説明は次のとおりです。sedプログラムは、1行に配置された2つの部分で構成されています。拡張バージョンは次のとおりです。

sed '
    s/ //
    s/ \([^[:lower:]]\)/,\1/g
'

プログラムはsed入力の各行に対して動作します。つまり、行を読み取り、一連の変換を適用してから、その行を印刷します。その後、読み取る行がなくなるまで、次の行から始めます。

ここで、最初のsedコマンドはs/ //「#」と次の数字を一緒に入れるために最初のスペースを削除します。

次に、2番目のsedコマンドはs/ \([^[:lower:]]\)/,\1/g各フィールドの先頭(「<space> <小文字以外のすべて>」と定義されています)を検索し、スペースをコロンで置き換えます。次のフィールドの最初の文字を表す\1角括弧 ""の間の正規表現を参照します。\([^[:lower:]]\)

残りの部分はテストです。sedファイルの内容やコマンドの出力を入力する代わりに、変数smartctl_output(サンプルで構成される文字列)を入力し、そのcsv変数に結果を代入します。

[アップデート#2]

これで、フィールドは複数のスペースで区切られているようです。以前よりずっと簡単になりました。コマンドはsed次のとおりです。

sed 's/  \+/,/g'

つまり、2つ以上のスペースで構成されるすべての系列をコロンに置き換えます。

答え2

シェルでローカルでこれを行う方法は考えられませんが、たとえば、次のように定義できますperl正規表現フィールドを分割するには、目的の単一の区切り文字を挿入し、別のIFS=,方法を使用して簡単に読み取ることができます。

あなたの例に応じて、フィールドはスペースで区切られ、その後に次のようになります。

  1. 大文字またはハイフン
  2. 少なくとも2つの数字からなるシーケンス

だからコマンドをパイプしてください。

. . . | 
  perl -F'[[:space:]](?=[[:upper:]-]|[[:digit:]]{2,})' -anle 'print join ",", @F'

関連情報