如何將空數組元素設置為零?
我正在編寫一個將命令結果發送到輸出數組的腳本。它涉及檢查伺服器的日誌並檢索它們的大小,但是在某些情況下伺服器具有故障轉移主機。在這些情況下,我需要腳本來檢查兩個主機並返回值。我遇到的問題是,如果任何輸出數組元素為空(意味著伺服器中不存在要檢查的文件,在其各自的回顯顯示中僅返回一個空格),它會導致數組索引發生變化。這意味著應該在輔助主機陣列集中的東西會撞到主陣列集中。相反,我希望將這些空索引儲存為 0 作為佔位符,以防止發生轉移。這是索引偏移明顯的地方:
echo The primary overall log value is ${output[0]}. echo The primary obs log value is ${output[2]}. echo The primary tracks log value is ${output[4]}. echo echo The secondary overall log value is ${output[6]}. echo The secondary overall log value is ${output[8]}. echo The secondary overall log value is ${output[10]}.
例如,如果輸出
$$ 2 $$和$$ 4 $$為空,輸出$$ 6 $$ 將向上移動到對應於輸出的行$$ 2 $$. 我已經嘗試過這個解決方案,但沒有運氣:
s=0 for x in "${output[@]}" do( x= if [[ -z $x ]]; then( x=0 echo $x) else echo fi s=s+1) done
所有這一切都是在輸出回波發生之前吐出零,並且不會針對任何索引偏移進行調整。
注意:這是輸出數組的來源,以及下面的修復嘗試:
for h in "${host[@]}" do for path in "${paths[@]}" do output+=( $(ssh $h du -sh $path) ) for x in "${!output[@]}"; do( if [[ -z "${output[$x]}" ]]; then output[$x]=0; fi; ) done done done
其中 host 和 path 已經定義了數組。我還要注意,對於只有一個主機可以訪問的情況,腳本功能很好,並且那裡的數組索引沒有問題。
例如,如果輸出
$$ 2 $$和$$ 4 $$為空,輸出$$ 6 $$將向上移動到對應於輸出的行$$ 2 $$.
在這種情況下,您實際上並沒有空值來代替 2 和 4,只是您的值比您預期的要少。
考慮數組分配:
array1=(a b c d) array2=(A D)
第一個設置
array1[0]
toa
,array1[1]
tob
等。第二個設置array2[0]
toA
和array2[1]
toD
。沒有辦法知道A
和之間是否應該有空值D
。他們需要明確地在任務中:array2=(A "" "" D)
您可能正在以
output
其他方式填充數組,但由於您沒有顯示它是如何完成的,因此無法對其發表評論。您可能遇到與上述類似的情況:“空”值根本不會被填充output
數組的任何值視為值。如果您從擴展中分配給數組,並且依賴於分詞,那麼您將無法避免這種情況。(即使
IFS
只包含換行符,它也會將連續的空換行符折疊為一個,刪除空行)。如果您使用mapfile
,則預設情況下空行應顯示為數組元素。在任何情況下,將空數組元素歸零的循環都不起作用,因為您沒有分配給循環內的數組(根本沒有分配),即使您這樣做了,循環體也會在子shell中執行(由括號
(...)
),所以任何賦值都不會發生在循環體之外。您不能真正使用 a
for x in "${output[@]}"
來有效地修改數組元素,因為x
只獲取數組值的副本,修改它不會更改原始值。您需要遍歷數組索引才能指向數組:somearray=(1 "" "" 4) for i in "${!somearray[@]}"; do if [[ -z "${somearray[$i]}" ]]; then somearray[$i]=0; fi; done echo "${somearray[@]}"
列印
1 0 0 4
。在您添加的範常式式碼中,分配
output+=( $(ssh $h du -sh $path) )
不會添加任何空元素。缺少的路徑將從數組中省略。首先考慮一下,du $path
如果路徑不存在,則不列印任何內容。(除了一個錯誤,但這會進入 stderr,並且不會被命令替換擷取。)此外,即使它確實列印了一個空行(或空格/製表符),分詞也會刪除連續的空格。試試 eg
array=( $( printf "foo\n\nbar\n" ) )
,它會創建一個包含兩個元素的數組。此外,替換循環中的括號啟動了一個子shell,因此對數組的任何修改都只會在該子shell中生效。通常,您不希望使用括號對 shell 命令進行分組,除非您知道您特別需要一個子 shell。
您可以在命令替換 ( ) 周圍加上引號,
"$(ssh ... du)"
以確保您得到一個字元串,但您可能希望將大小與路徑名分開。嘗試像這樣將路徑及其大小收集到單個數組中:
for host in "${hosts[@]}"; do for path in "${paths[@]}"; do output="$(ssh "$host" du -sh "$path")" size="${output%%$'\t'*}" # needs Bash/ksh/zsh size="${size:-0}" sizes+=( "$size" "$host:$path" ) done done
現在,每個偶數數組元素都包含一個大小,每個奇數元素都包含一個相應的主機名和路徑,有點像拆分輸出的
du
結果。兩個參數擴展output
和size
刪除選項卡後的所有內容,然後將大小替換為如果它是空的,則為零。或者,您可以建構一個關聯數組,由主機+路徑索引:
declare -A array ... array["$host:$path"]=$size