一个bash命令,它使用另一个bash命令的输出

时间:2017-01-22 13:20:12

标签: linux bash

我在谷歌云端有一组机器。 来自我的localhost:

function index()
    {
        $user = $this->session->userdata("id");
        $data = $this->customer_model->get_rol_user($user);

        foreach ($data as $key=>$value) {
          if ($row[$key]->Url === 'customer/index'){
               $this->load->view('guest/head');
               $this->load->view('guest/nav');
               $this->load->view('guest/section');
               $this->load->view('customer/customer_view');
            }
         }
            redirect(base_url());

        }

我想从第一个命令中获取该列表中的随机工作者名称(比如说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
bash上的一点点弱点。请帮忙

3 个答案:

答案 0 :(得分:3)

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

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

执行此命令后,您就可以使用machinezone个变量,例如:

gcloud compute --project "my-project" ssh --zone "$zone" "$machine"

<强>说明

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

使用command substitution捕获 gcloud perl 命令的输出,并通过{{3}传递给读取命令}。

我在第一段中引用了 words ,因为shell根据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'
)

其中<>读取标题; $.是保留当前行号的内置变量;其余的来自IFS

答案 1 :(得分:2)

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 does only pass variables to subprocesses中的管道,而不是父进程。以下脚本通过在父进程中运行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"

答案 2 :(得分:2)

如果从中提取随机行的输入很大,并且你想避免将其作为一个整体整体读入内存,那么考虑第二个{{1在Ruslan Osmanov's helpful answer中的解决方案。

否则,hansaplast's helpful answer使用基于shuf的多实用程序方法,该方法易于理解,但可以简化(并且在撰写本文时,有缺陷):

perl
  • 通过使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" )的输出,确保在当前 shell中执行read ,这意味着它创建的变量对其余命令可见,特别是第二次<(...)调用。

    • 相比之下,如果您使用管道(read),gcloud子shell 中执行,则后续命令将无法看到它创建的变量。
  • gcloud ... | read ...会跳过输入中的第一行(标题行)。

  • read从输入中提取1个随机选择的行。

  • 注意tail +2作为传递给shuf -n 1的第3个变量的名称,它接收前2个后输入行的(未使用的) rest 已将空格分隔的标记读入_read

    • 如果我们只指定了$machine$zone,则machine不仅会收到第二个令牌,还会收到输入行的其余部分。