如何检查while循环是否执行?

时间:2013-05-14 16:04:05

标签: bash

cat list.txt | grep '^http://.*\.osm\..*$' | while read line; do
    fn=$(basename $line)
    do_something()
done
# TODO: check if it did something

如果grep命令什么都不返回,它将不会进入循环,并且 do_something()将不会被执行。

我无法检查while循环之外的$ fn中的内容,请参阅Bash variable scope

检查 do_something()是否在此处执行的最少侵入性解决方案是什么?

5 个答案:

答案 0 :(得分:3)

如果执行循环,您可以使用其值将被更改的flag。下面是一个poc。

shopt -s lastpipe   # bash 4.2 or greater only
flag="false"
cat list.txt | grep '^http://.*\.osm\..*$' | while read line; do
    fn=$(basename $line)
    do_something()
    flag="true"
done

if [ "$flag" = "true" ]
then
    echo "loop was executed"
fi

如果while跨越sub-shell,则需要使用以下内容(感谢所有评论如下的人)

 while read line
   do
       fn=$(basename $line)
       do_something()
       flag="true"
   done < <(grep '^http://.*\.osm\..*$' list.txt)

答案 1 :(得分:3)

由于while循环在子shell中运行,因此它无法将值传播回父shell。但是,仍然有办法做想要的事情。这是一个:

if grep -q '^http://.*\.osm\..*$' list.txt       # loop will definitely run
then
  while read line
  do
    # do something with line
  done < <(grep '^http://.*\.osm\..*$' list.txt)
else                                             # no matches, loop will not run
  # do something else
fi

它有两次运行grep的副作用,这可以通过保存grep的输出并对其进行后处理来避免,如另一个答案所示,但在某些方面,这是一个有点简单了解......

答案 2 :(得分:2)

grep的输出保存在变量中并明确测试。

filtered=$(cat list.txt | grep ....)

if [ -z "$filtered" ] ;
  ... handle empty output ..
 else
  ... do your while loop here... 
fi

顺便说一句:新行保留在"$filtered"内,但请务必在使用时引用它。

答案 3 :(得分:2)

您可以使用流程替换来代替管道,这将允许有用地设置标志:

flag=0
while read line; do
    flag=1
    fn=$(basename $line)
    do_something()
done < <( grep '^http://.*\.osm\..*$' list.txt )

if [[ $flag == 1 ]]; then
   ...
fi

答案 4 :(得分:1)

@chepner解决方案的变体:

flag=0
while read line; do
    grep -q '^http://.*\.osm\..*$' <<< $line && {
      flag=1
      fn=$(basename $line)
      do_something()
    }
done < list.text

if [[ $flag == 1 ]]; then
   ...
fi

然后使用一个更符合您需求的产品。