【问题标题】:My shell script 'break' statement not working我的 shell 脚本“break”语句不起作用
【发布时间】:2019-11-20 03:58:35
【问题描述】:

我想打破嵌套的 while 循环。

以下是我在代码中尝试过的,

while [itretative condition]
do
   ...
   ...
      cat test1.json | while read line
      do
        ...
        ...
           cat test2.json | while read line
           do
             ...
             ...
                if [ "$taskstatus" = "RUNNING" ]
#when my task status reach running, i want to stop the script execution and end it.
                break 3       #break 3 or exit is not working for me.
                fi
           done
      done
done

请建议我如何实现这一目标?

【问题讨论】:

  • 你的缩进太疯狂了,当边距随机跳跃时,真的很难理解应该发生的事情。另外,您能否解释一下您的期望,以及输出的错误之处?
  • 对不起我的缩进,我的期望是!当任务状态达到“RUNNING”状态时..我希望脚本优雅地结束,我不想进一步循环并测试但结束它。
  • 如果这是你的整个脚本,那么exit 会很轻松地做到这一点。如果您无法解决问题,我认为您无法让任何人看到它。另请参阅创建minimal reproducible example 的指南。
  • 嗨,我尝试退出,但对我来说没有成功。根据您的建议,我通过删除所有不必要的信息来表示代码。
  • 管道 (cat somefile | while ...) 在子 shell 中运行它们的内容,并且子 shell 不能中断父 shell 中的循环(或退出父 shell,或者...)。你能用while read ... done <somefile替换cat管道吗?

标签: bash shell loops nested-loops break


【解决方案1】:

每当您使用管道时,都会创建一个子外壳。 Neiter breakexit 在子 shell 边界上工作。

即使trap 也不能在子外壳边界上工作。但是set -E 选项告诉 Bash 继承父 shell 的错误处理程序。通过这种方式,您可以保留一个特殊的退出代码来实现break 逻辑。

以下代码分为外壳和子外壳,它们使用管道运行您的代码并创建更多子外壳。

外壳的错误处理程序不被子shell继承,因为默认情况下陷阱处理程序继承是禁用的。外壳的错误处理程序只检查保留的退出代码(示例中为 42)并将其视为无错误。

在第一个子外壳错误处理程序继承由set -E 启用。这意味着所有子 shell 共享相同的错误处理程序。子 shell 错误处理程序只是传递错误代码并终止 shell。这样所有的子shell都被终止了。

#! /bin/bash

err()
{
  local err=$?
  if (( err == 42 )); then
    exit
  else
    exit $err
  fi
}
trap err ERR

(
  set -E

  err()
  {
    local err=$?
    exit $err
  }

  trap err ERR

  printf "%s\n" a b c | while read i; do
    echo $i
    printf "%s\n" x y z | while read j; do
      echo $j
      exit 42
    done
  done
)

【讨论】:

    【解决方案2】:

    如 cmets 中所述,break 语句不适用于从管道创建的子 shell。对于管道只是 cat file | while 的简单情况,可以使用 while read ... done <somefile 将表达式“去除管道”(上面的 Gordon Davisson 评论)。

    对于更一般的情况,管道可以包含任意命令(grep x file1grep y file2,在下面的示例中),可以使用de-pipe 命令(并允许中断在多个级别上工作)使用以下方法之一:(1) 这里的文档 (2) 进程替换。

    这里有文件:<<<"$(commands)"

    while read x  ; do
       while read y ; do
           echo "$x/$y" ;
           [[ "$x" = d* ]] && echo BREAK && break 2 
       done <<< $(grep y file2); 
    done <<< "$(grep x file1)"
    

    使用进程替换&lt; &lt;(commands)

    while read x  ; do
        while read y ; do
            echo "$x/$y" ;
            [[ "$x" = d* ]] && echo FOO && break 2 ;
        done < <(grep y file2);
    done < <(grep x file1)
    

    【讨论】:

      猜你喜欢
      • 2013-03-25
      • 2012-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多