shell 如果不满足条件,则从上一状态重新启动循环

nr9pn0ug  于 2023-02-24  发布在  Shell
关注(0)|答案(6)|浏览(190)

问题在于,如果条件不为真,它应该“停止”for循环,或者除非满足该值,否则不应该继续。
假设在for循环中有一个输入语句true/false或一个布尔语句,输出为1到10。
如果条件在第5次迭代中为假,则应停留在第5次迭代中,直到布尔值返回真。

for i in {1..10}
do
        read jobstatus
#       echo $i
        if [ "$jobstatus" = true ] ; then
                echo 'Okay lets progress'
        else
                echo 'Nop, cant progress'
                ((i--))
        #       continue
#print $i
        fi
        echo $i
done

我试过编写这样的代码,也通过编写充当“标志”的文件来检查它,但我似乎不能“停止”进程。我不想打破循环,我只想让它停留在特定的迭代中,直到状态发生变化。就像如果作业状态在i=5时出错,除非jobstatus变为true,否则我应该保持5。(我打算在每次输入时检查jobstatus)

nzk0hqpo

nzk0hqpo1#

您可以将循环结构如下:

#!/bin/bash

i=0
while test "$i" -lt 10; do
        while read jobstatus && test "$jobstatus" != true; do
                echo "can't progress.  jobstatus = $jobstatus" >&2
        done
        if test "$jobstatus" = true; then
                echo "Okay lets progress to step $((++i))"
        else
                echo Unexpected End of input >&2
                exit 1
        fi
        echo "$i"
done
vhipe2zx

vhipe2zx2#

使用C风格的for循环:

#!/bin/bash
for ((i=1; i<=10; ++i)) ; do
    read jobstatus
    if [ "$jobstatus" = true ] ; then
        echo 'Okay lets progress'
    else
        echo 'Nop, cant progress'
        ((i--))
    fi
    echo $i
done
xyhw6mcr

xyhw6mcr3#

if测试应该是某种循环。例如:

for i in {1..10}
do
    while
        read jobstatus
        [ "$jobstatus" != true ]
    do
        echo 'Nop, cant progress'    
    done
    echo 'Okay lets progress'

    echo $i
done

如果你想重复其他的for命令(例如这里的echo $i语句)直到测试成功,它们也应该进入循环。

for i in {1..10}
do
    while
        echo $i
        read jobstatus
        [ "$jobstatus" != true ]
    do
        echo 'Nop, cant progress'
    done
    echo 'Okay lets progress'
done
emeijp43

emeijp434#

这可能是你正在寻找的:

for i in {1..10}; do
  read jobstatus
  if [ "$jobstatus" != true ]; then
    echo 'Nop, cant progress'
  fi

  while [ "$jobstatus" != "true" ]; do
    read jobstatus
    sleep 1
    # echo statements here if needed
  done

  echo 'Okay lets progress'
  echo $i
done

不需要递减i,这也避免了过于频繁地检查jobstatus的状态,从而潜在地消耗不必要的资源量。

mlmc2os5

mlmc2os55#

通过交互式用户输入,可能是这样的:

#!/bin/sh

i=0
while [ "$i" -lt 10 ] && printf 'Enter status: '; do
  IFS= read -r jobstatus
  case "$jobstatus" in
    true)
    i=$((i+1))
    printf 'Okay lets progress to %s' "$i";;
  *)
    printf >&2 'Nop, cant progress because jobstatus is: %s' "${jobstatus:-empty}"
  esac
  printf '\n'
done

使用文本文件作为输入,来测试脚本。
file.txt

true
true
true
true
true
false
foo
bar
baz

true
true
true
true
qux

true
false

脚本:

#!/bin/sh

i=0
while [ "$i" -lt 10 ] && IFS= read -r jobstatus; do
  case "$jobstatus" in
    true)
    i=$((i+1))
    printf 'Okay lets progress to %s' "$i";;
  *)
    printf >&2 'Nop, cant progress because jobstatus is: %s' "${jobstatus:-empty}";;
  esac
  printf '\n'
done < file.txt

输出:

Okay lets progress to 1
Okay lets progress to 2
Okay lets progress to 3
Okay lets progress to 4
Okay lets progress to 5
Nop, cant progress because jobstatus is: false
Nop, cant progress because jobstatus is: foo
Nop, cant progress because jobstatus is: bar
Nop, cant progress because jobstatus is: baz
Nop, cant progress because jobstatus is: empty
Okay lets progress to 6
Okay lets progress to 7
Okay lets progress to 8
Okay lets progress to 9
Nop, cant progress because jobstatus is: qux
Nop, cant progress because jobstatus is: empty
Okay lets progress to 10
zazmityj

zazmityj6#

请尝试以下Shellcheck-clean Bash代码:

#! /bin/bash -p

for ((truecount=0; truecount<10;)); do
    read -r jobstatus
    if [[ $jobstatus == true ]]; then
        echo "Okay let's progress"
        (( ++truecount ))
    else
        echo "Nope, can't progress"
    fi
    printf '%d\n' "$truecount"
done
  • 与原始代码相比,主要的变化是它只在“真”状态下前进,而不是总是在非“真”状态下前进和后退。一般来说,最好只能在一个地方修改循环变量。
  • 由于代码不只是单步执行一个序列,所以我用描述性的truecount替换了无意义的i
  • 请参阅Why is printf better than echo?的公认的、优秀的答案,以解释为什么我使用printf而不是echo来打印计数值(echo "$truecount"在这个特定的情况下可能是可以的,但是echo "$var"通常不起作用,所以我从不使用它。echo $var是坏的。请参阅Bash陷阱#14(echo $foo))。

相关问题