Bash

bash - 將“表”值分隔為數組中的字元串

  • January 7, 2017

編輯:對不起,我聲稱的輸出是錯誤的。空格比我之前想像的要多(輸出保存到 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' &lt;&lt;&lt; "$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'

這意味著:用冒號替換所有兩個或多個空格的系列。

引用自:https://unix.stackexchange.com/questions/335504