在while循环中中断if语句

时间:2017-01-31 13:02:57

标签: bash loops if-statement while-loop exit

不确定是否可行,但我试图突破if循环中的while语句。我不想退出while循环。我尝试使用exitbreak,但都退出了while循环。

问题是我不知道我要查找的文件位于哪个文件夹中,这就是为什么我想在匹配搜索到的文件时退出当前的if语句,以便我可以转到下一个序列号。

我有一个名为drives-fw-sn.txt的文本文件,其中包含序列号列表。代码细分:

  • 我使用drives-fw-sn.txt循环从while一次读取一个序列号
  • 我使用output_log
  • 搜索名为find的文件
  • 然后我从找到的文件
  • 中打印出第一次出现的序列号
  • 接下来我打印出已找到日志并希望

这是我的代码片段(有三个以上的测试文件夹)。请注意,它仍然包含退出exit循环的while命令。

while read node; do
   if find ./test1/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
     echo "Log SN $node available"
     exit 1
   fi
   if find ./test2/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
     echo "Log SN $node available"
     exit 1
   fi
   if find ./test3/*log* -maxdepth 2 -type f -name output_log -exec egrep -m 1 $node {} \; ; then
     echo "Log SN $node available"
     exit 1
   fi
done < drives-fw-sn.txt

3 个答案:

答案 0 :(得分:1)

本身无法突破if。但是从您的示例的外观来看,您可以使用continue命令而不是exit来立即迭代循环。

答案 1 :(得分:1)

使用内置的return实际上非常简单。在while循环内,在一个小的功能块中设置if语句。在迭代期间满足if条件时,您可以让它调用return,其中脚本将返回到调用函数的位置并从该点继续。我将向您展示一个例子:

#!/bin/bash

read -p 'Input: ' HEY

func() { if true; then return; fi; }

while true; do

   echo "Input received!"
   func && break

done

func函数中,您有一个非常基本的if语句,可以保存您想要的任何条件值,例如您的多个条件。当您添加return关键字时,if语句会发送解释程序&#34;程序计数器&#34;,如果愿意,则返回{{1}函数被调用。在这种情况下,在func循环内。所以就好像甚至没有调用函数一样,你可以看到,while循环中的下一个命令是一个while关键字,它将结束break循环。包含while代码的函数可以在if-then-return循环内部或外部,只要放在while语句中的条件已经首先加载到解释器中(bash读取脚本)从上到下,类似于C代码的加载方式。)

还有一个惰性方法,即将整个脚本代码包装在main函数中,这样您就可以在脚本中的任何位置使用if,无论它是循环还是条件语句。以下是以这种方式修改的上述脚本的示例:

return

以这种方式执行此操作将有助于将变量保持在本地而不是创建全局变量。要做到这一点,在#!/bin/bash MAIN() { read -p 'Input: ' HEY while true; do if [ "$HEY" == "hello" ]; then return else echo "Incorrect input! Try again!" MAIN fi done } MAIN echo "Correct input received!" 函数中的任何一点,您都可以将变量定义为局部变量,因此它只保存MAIN函数运行时给定的值。函数完成后,变量及其值不再存在。

希望这有帮助。

答案 2 :(得分:0)

continue是您如何“突破”if声明的具体问题的正确答案。请注意,if检查实际上并未检查grep是否成功,请参阅chepner的评论。

我会以一种首先解决问题的方式来做到这一点:

由于您不知道包含序列号的文件将位于哪个目录中,因此您查看它们的顺序无关紧要。不是单独列出所有目录并在每个目录上运行find -exec,而是让grep直接尝试所有日志文件:

while read -r node; do
    cat **/output_log | grep -m 1 "$node" && echo "Log SN $node available"
done < drives-fw-sn.txt

这需要globstar shell选项shopt -s globstar来启用**/构造。根据您的目录结构,您甚至可能不需要它,而是可以使用类似test*/*log*/output_log的内容。

cat用于防止grep在找到匹配后检查其他文件。

输出略有不同:匹配以文件名为前缀,但可以使用相应的grep选项(-h来调整)来抑制文件名。

看起来你也不需要正则表达式匹配;如果是这样,您可以将grep -F用于固定字符串,这应该更快。

最后,根据序列号的外观,您可能希望使用-w选项(仅匹配完整的单词)以避免因子字符串匹配而产生误报。