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 還比較陌生。
無論如何,我正在使用 Smartmontools 來檢測並通知我是否有任何 SMART 錯誤。它按我的意願工作,但我想獲得一些關於 HDD 的每日統計資訊,所以我製作了自己的腳本,從 smartmontools 和其他有趣的東西(如臨時、SMART 值和使用的 HDD 空間)收集資訊。可能不是做這樣的事情的最佳方式,但我喜歡這樣做,而且我邊走邊學。
我發送的電子郵件被格式化為 HTML 以製作表格並為正面/負面結果添加字型顏色(綠色/紅色)。但是當我試圖製作一張表來顯示自測時,我遇到了一些問題。
我正在使用的命令是:(
sudo smartctl -l selftest $HDD | grep '#' >> $SMARTFILE
在一個循環中 $ HDD is all the HDD in my system and $ 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
如果有不清楚的地方或需要任何其他資訊,請告訴我。
從上面的(小)
smartctl
消息範例中,似乎它們的部分基本上由“<space><anything but a lowercase>”分隔(除了行首的“# 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 一樣填充陣列。
$$ update $$ 以下是對
sed
拆分部分的解釋:sed
程序由我放在一行中的兩部分組成。這是擴展版本:sed ' s/ // s/ \([^[:lower:]]\)/,\1/g '
程序
sed
對輸入的每一行進行操作:它讀取一行,應用一組轉換,然後列印該行。然後它從下一行重新開始,直到沒有更多的行可供閱讀。這裡第一個
sed
命令s/ //
刪除第一個空格以將“#”和以下數字放在一起。然後,第二個
sed
命令s/ \([^[:lower:]]\)/,\1/g
搜尋每個欄位的開頭(由“<space><anything but a lowercase>”定義)並用冒號替換空格。\1
引用括號“”之間的正則表達式,\([^[:lower:]]\)
表示下一個欄位的第一個字元。剩下的部分是一個測試:我沒有
sed
輸入文件的內容或命令的輸出,而是輸入了變數smartctl_output
(由您的樣本組成的字元串)並將結果分配給csv
變數。$$ update #2 $$ 現在看來,這些欄位由兩個或多個空格分隔。它比以前更容易。
sed
命令變為:sed 's/ \+/,/g'
這意味著:用冒號替換所有兩個或多個空格的系列。