[英]a bash command that uses the output of another bash command
我在谷歌雲有一組機器。 來自我的localhost:
gcloud compute instance-groups list-instances workers
OUTPUT:
NAME ZONE STATUS
workers-lya2 us-central1-a RUNNING
workers-23d4 us-central1-a RUNNING
...
workers-3asd3 us-central1-a RUNNING
我想從該列表中選擇一個隨機工作者名稱(比如workers-23d4
),然后從第一個命令開始區域us-central1-m
並將其粘貼到此命令中:
gcloud compute --project "my-project" ssh --zone "<zone_name_from_first_command> "<machine_name_from_first_command>"
bash上的一點點弱點。 請幫忙
以下命令從gcloud命令的輸出中選擇一個隨機行(不包括標題),然后將前兩個“單詞”存儲到machine
和zone
變量中:
read -r machine zone unused <<< $(
gcloud compute instance-groups list-instances workers | \
perl -e '@_ = <>; shift @_; print $_[rand @_]'
)
在此命令之后,您可以使用machine
和zone
變量,例如:
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"
說明
perl命令使用菱形運算符<>
讀取標准輸入到@_
數組的所有行。 然后shift
函數從@_
刪除第一個項目。 rand
@_
返回0和@_
中項目數之間的隨機十進制數。 十進制數在索引上下文中隱式轉換為整數。 因此,結果$_[rand @_]
是一個隨機項@_
,即,從gcloud指令的輸出的隨機線。
使用命令替換捕獲gcloud和perl命令的輸出,並通過此字符串傳遞給read命令。
我在第一段中引用了單詞 ,因為shell根據IFS
( 輸入字段分隔符 )變量將字符序列解釋為單詞。 因此,來自here字符串的IFS
分隔的單詞被分配給machine
(第一個單詞), zone
(第二個單詞)和unused
(其余行)變量。
-r
選項禁用反斜杠的特殊含義。 換句話說,當給出此選項時, read將不會嘗試解釋輸入中的轉義序列。
大數線的案例
注意,解決方案意味着gcloud命令的輸出相對較小,即小到足以將整個文件粘貼到數組中。 此操作很快,但需要更多內存,而不是使用while <>
循環逐行讀取。 如果輸出非常大,或者內存非常有限,這是另一種解決方案:
read -r machine zone unused <<< $(
gcloud compute instance-groups list-instances workers | \
perl -e '<>; $. = 0; rand($.) < 1 && ($line = $_) while <>; print $line'
)
其中<>
讀取標題; $.
是保持當前行號的內置變量; 其余的都來自這本食譜 。
gcloud compute instance-groups list-instances workers | grep -v "^NAME" | shuf -n 1 | awk '{print $1, $2}' |
while read machine zone; do
export SELECTED_MACHINE="$machine"
export SELECTED_ZONE="$zone"
done
gcloud compute --project "my-project" ssh --zone "$SELECTED_ZONE" "$SELECTED_MACHINE"
grep -v "^NAME"
剝離所有以NAME
開頭的行(假設它只是你要剝離的第一行) shuf
從剩余的行中取一條隨機行 awk '{print $1, $2}'
在空格處分割行並打印第一列和第二列 while read
讀取awk的輸出到變量$machine
和$zone
更新 :上面的代碼適用於zsh,但不適用於bash,因為bash在子shell中運行管道(zsh不運行), export
只傳遞變量到子進程,而不是父進程。 以下腳本通過在父進程中運行read
來解決此問題:
machine_zone=$(gcloud compute instance-groups list-instances workers |
grep -v "^NAME" | shuf -n 1 | awk '{print $1, $2}')
read machine zone <<< $machine_zone
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"
如果從中提取隨機行的輸入很大,並且你想避免將其作為一個整體讀入內存,就像shuf
那樣,請考慮Ruslan shuf
的第二個perl
解決方案。
否則, hansaplast的有用答案使用基於shuf
的多實用程序方法,這種方法易於理解,但它可以簡化(並且,在撰寫本文時,有缺陷):
read -r machine zone _ < \
<(gcloud compute instance-groups list-instances workers | tail +2 | shuf -n 1)
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"
通過read
進程替換( <(...)
)的read
,確保在當前 shell中執行read
,這意味着它創建的變量對其余命令可見,特別是第二次gcloud
調用。
gcloud ... | read ...
),則read
在子shell中執行,並且后續命令將不會看到它創建的變量。 tail +2
跳過輸入中的第一行(標題行)。
shuf -n 1
從輸入中提取1個隨機選擇的行。
注意_
作為傳遞給read
的第3個變量的名稱,它在前2個以空格分隔的標記被讀入$machine
和$zone
之后接收輸入行的(未使用的) 其余部分 。
machine
和zone
, $zone
將不僅接收第二個令牌,而且還接收輸入行的其余部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.