首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用另一个bash命令的输出的bash命令。

使用另一个bash命令的输出的bash命令。
EN

Stack Overflow用户
提问于 2017-01-22 13:20:11
回答 3查看 856关注 0票数 3

我在谷歌云有一组机器。我的本地人:

代码语言:javascript
复制
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粘贴到下面的命令中:

代码语言:javascript
复制
gcloud compute --project "my-project" ssh --zone "<zone_name_from_first_command> "<machine_name_from_first_command>"

有点虚弱的巴什。请帮帮忙

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-22 13:36:57

代码语言:javascript
复制
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

Update:上面的代码适用于zsh,但不适用于bash,因为bash在子doesn (zsh不运行)和只将变量传递给子进程吗? (而不是父进程)中运行管道。下面的脚本通过在父进程中运行read来解决这个问题:

代码语言:javascript
复制
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"
票数 2
EN

Stack Overflow用户

发布于 2017-01-22 16:15:18

以下命令从gcloud命令的输出中选择一个随机行(不包括标头),然后将前两个“单词”存储到machinezone变量中:

代码语言:javascript
复制
read -r machine zone unused <<< $(
  gcloud compute instance-groups list-instances workers | \
    perl -e '@_ = <>; shift @_; print $_[rand @_]'
)

在这个命令之后,就可以使用machinezone变量了,例如:

代码语言:javascript
复制
gcloud compute --project "my-project" ssh --zone "$zone" "$machine"

解释

perl命令使用菱形操作符<>将标准输入的所有行读入<>数组。然后shift函数从@_中移除第一项。rand@_在零和@_中的项目数之间返回一个随机十进制数。十进制数在索引上下文中隐式转换为整数。因此,$_[rand @_]的结果是@_的一个随机项,即从gcloud命令输出的随机行。

使用命令替换捕获gcloud和perl命令的输出,并通过这里串传递给read命令。

我引用了第一段中的单词,因为shell根据IFS (输入字段分隔符)变量将字符序列解释为单词。因此,这里字符串中的IFS-separated单词被分配给machine (第一个单词)、zone (第二个单词)和unused (行的其余部分)变量。

-r选项禁用反斜杠的特殊含义。换句话说,在给定此选项时,read将不会尝试解释输入中的转义序列。

--大数线的情形

注意,该解决方案意味着gcloud命令的输出相对较小,即足够小,足以将整个文件读入数组。此操作速度快,但需要更多内存,而不是使用while <>循环逐行读取。如果输出非常大,或者内存非常有限,下面是另一种可能的解决方案:

代码语言:javascript
复制
read -r machine zone unused <<< $(
  gcloud compute instance-groups list-instances workers | \
    perl -e '<>; $. = 0; rand($.) < 1 && ($line = $_) while <>; print $line'
)

其中<>读取标头;$.是保持当前行号的内建变量;其余的则从这本食谱获取。

票数 3
EN

Stack Overflow用户

发布于 2017-01-22 17:17:30

如果从其中提取随机行的输入很大,并且您希望避免像shuf那样将其作为一个整体读入内存,那么请考虑罗斯兰·奥斯马诺夫的有益回答中的第二个perl解决方案。

否则,hansaplast的有用答案使用一种基于shuf的多实用程序方法,该方法易于理解,但可以简化(而且,在撰写本文时,它存在缺陷):

代码语言:javascript
复制
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读取进程替换(<(...))的输出,可以确保在当前shell中执行read,这意味着它创建的变量对其余命令是可见的,特别是第二个gcloud调用。
代码语言:javascript
复制
- By contrast, if you use a pipeline (`gcloud ... | read ...`), `read` executes in a _subshell_, and the variables it creates won't be seen by subsequent commands.

  • tail +2跳过输入中的第一行(标题行)。
  • shuf -n 1从输入中提取一个随机选择的行。
  • 注意,_作为传递给read的第三个变量的名称,在将前2个空格分隔的令牌读入$machine$zone之后,该变量接收输入行的(未使用)其余部分。
代码语言:javascript
复制
- If we only specified `machine` and `zone`, the `$zone` would receive not just the 2nd token, but the entire rest of the input line.

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41791386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档