下面的命令从
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
@_
返回介于零和 @_
中项目数之间的随机十进制数。在索引上下文中,该十进制数会被隐式转换为整数。因此,$_[rand @_]
的结果是 @_
的一个随机项,即来自 gcloud 命令输出的一行随机内容。
使用命令替换 捕获 gcloud 和 perl 命令的输出,并通过here string 传递给 read 命令。
第一段中我用引号引起了 单词,因为 shell 根据 IFS
(输入字段分隔符) 变量将字符序列解释为单词。因此,来自 here string 的以 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'
)
其中 <>
读取头部信息,$.
是内置变量,保存当前行号;其余内容来源于此教程。