1

bash if 语句中是否可以有两个表达式,使用“或”运算符,其中一个表达式测试 grep 的退出状态?

例如,我想要一个脚本来处理我的 PATH 中'.'之外的所有目录。和 /home/$LOGNAME/bin。我可以用两个 if 语句来做这件事,但我想将这两个测试组合成一个由“或”连接的语句。

这是工作版本(两个单独的 if 语句):

IFS=:

for VAR in $PATH ; do
  if echo $VAR | grep /home/$LOGNAME/bin > /dev/null
  then
    echo SKIPPING YOUR OWN bin DIRECTORY \($VAR\)
  elif [ "$VAR" = "." ]
  then
    echo SKIPPING CURRENT WORKING DIRECTORY \($VAR\)
  else
    echo processing $VAR
  fi
done

..产生以下输出:

SKIPPING CURRENT WORKING DIRECTORY (.)
SKIPPING YOUR OWN bin DIRECTORY (/home/bobo/bin)
processing /home/qa/utils
processing /usr/lib64/qt-3.3/bin
processing /usr/local/bin
processing /bin
processing /usr/bin
processing /usr/local/sbin
processing /usr/sbin
processing /sbin

只是许多失败尝试中的一小部分:

if [ ( echo $VAR | grep /home/$LOGNAME > /dev/null )] -o [ "$VAR" = "." ]
if [[ ( echo $VAR | grep /home/$LOGNAME > /dev/null ) ]] -o [[ "$VAR" = "." ]]
if ( echo $VAR | grep /home/$LOGNAME > /dev/null ) -o "$VAR" = "."
if ( echo $VAR | grep /home/$LOGNAME > /dev/null ) || "$VAR" = "."
4

3 回答 3

2

if elif fi 块的正确形式可以是这样的。您也不需要使用外部二进制命令,例如grep.

IFS=:

for VAR in $PATH; do
  if [[ $VAR == . ]]; then
    echo "SKIPPING CURRENT WORKING DIRECTORY \($VAR\)"
  elif [[ "$VAR" == "/home/$LOGNAME/bin"* ]]; then
    echo "SKIPPING YOUR OWN bin DIRECTORY \($VAR\)"
  else
    echo "processing $VAR"
  fi
done

如果你想用一行来做,你可以有:

IFS=:

for VAR in $PATH; do
  if [[ $VAR != . && "$VAR" != "/home/$LOGNAME/bin"* ]]; then
    echo "processing $VAR"
  else
    echo "SKIPPING CURRENT WORKING DIRECTORY OR YOUR OWN bin DIRECTORY \($VAR\)"
  fi
done

或者

IFS=:

for VAR in $PATH; do
  if [[ $VAR == . || "$VAR" == "/home/$LOGNAME/bin"* ]]; then
    echo "SKIPPING CURRENT WORKING DIRECTORY OR YOUR OWN bin DIRECTORY \($VAR\)"
  else
    echo "processing $VAR"    
  fi
done

else块是可选的。

于 2013-09-10T14:08:37.373 回答
2

这是可能的,但完全没有必要。让我们直接if评估退出状态grep

if echo "$var" | grep -q "$HOME/bin" || test "$var" = . ; then
  ...
fi

或者

if echo "$var" | grep -q "^$HOME"'/bin$\|^\.$'; then ...

请注意,它们的语义略有不同,因为第二个要求 $HOME/bin 是整行,但这可能是您想要的。(如果是这种情况,锚点应该在第一个示例中。)

于 2013-09-10T14:08:43.390 回答
1

有几种方法可以做到这一点。使用您的if构造,它可能看起来像这样(尽管还有其他几种同样有效的方法):

if [[ "${VAR}" == "." ]] || grep -q /home/${LOGNAME}/bin <<< "${VAR}"

你也可以考虑这样的事情,我认为这会让你在做什么更清楚,甚至可以减少打字(它也省去了调用外部程序,所以效率会稍微高一些):

case "${VAR}" in
  .|*/home/${LOGNAME}/bin*) .... ;;
  *) .... ;;
esac
于 2013-09-10T14:10:29.983 回答