如何在bash脚本中正确使用带有&&和-o的elif

时间:2019-12-04 11:47:14

标签: bash if-statement

Bash版本4.4.20
Ubuntu 16.04

我需要比较我拥有的特定项目的时间和扩展名。以下是与我尝试执行的操作类似的操作,但错误相同。我不确定错误在哪里,因为shellcheck没有产生错误。

job

错误:

#!/bin/bash
#

while read -r filename; do
  extension="${filename##*.}"
  if [ "$extension" == "zip" ] && [ "$filename" == "one.zip" ]; then
    echo "Filename is $filename"
  elif [ "$extension" == "zip" ] && [ "$filename" == "file_1.zip" ] -o [ "$filename" == "file_2.zip" ] -o [ "$filename" == "file_3.zip" ]; then
    echo "Filename is $filename"
  elif [ "$extension" == "csv" ] && [ "$filename" == "two.csv" ]; then
    echo "Filename is $filename"
  else
    echo "Filename is $filename"
  fi
done<fileList.txt  

3 个答案:

答案 0 :(得分:3)

使用模式匹配来发挥自己的优势:

while IFS= read -r filename; do
  if [[ "$filename" = one.zip ]; then
    echo "Filename is $filename"
  elif [[ "$filename" = file_[123].zip ]; then
    echo "Filename is $filename"
  elif [[ "$filename" = two.csv ]; then
    echo "Filename is $filename"
  else
    echo "Filename is $filename"
  fi
done < fileList.txt

case语句将在任何 POSIX shell中运行,而不仅仅是支持类似bash的{​​{1}}命令的shell。

[[ ... ]]

要匹配年份范围(?),可以使用

while IFS= read -r filename; do
  case $filename in
    one.zip) echo "Filename is $filename" ;;
    file_[123].zip) echo "..." ;;
    two.csv) echo "..." ;;
    *) echo "..." ;;
  esac
done

您不能像使用case $value in 200[0-9]|201[0-9]|202[0-1]) echo "Year between 2000 and 2021" ;; esac 那样简单地执行此操作,因为[[ value = ... ]]|语句语法的一部分,而不是模式中的交替运算符。相反,您将需要多个匹配运算符:

case

答案 1 :(得分:3)

以下是为什么的解释,您将得到此错误,因为您已经获得正确执行操作的正确答案:

请注意,命令[test等效,因此,有效的第8行(还删除了不必要的引号)包含:

elif test "$extension" == zip ] && test "$filename" == file_1.zip ] -o [ "$filename" == file_2.zip ] -o [ "$filename" == file_3.zip ]

test 手册页中,我们可以看到结尾的]是可选的,但是如果存在,它将终止要测试的表达式。

第一个test,就是

test "$extension" == "zip" ] 
在这方面

很好,但是第二个以

开始
test "$filename" == file_1.zip ] -o [  ...

因此,当解析参数时,test会遇到一个]并知道这是参数的终结符,但随后又找到了另一个参数(-o),但没有找到知道该怎么办。因此,它抱怨说它有太多的论据

答案 2 :(得分:1)

我已经将语法更新为我认为的现代bash惯用语。该脚本现在可以工作了。如果我错过了其他事情,请纠正我:

#!/bin/bash
#

while read -r filename
do
  extension="${filename##*.}"
  if [[ "$extension" = "zip" &&  "$filename" = "one.zip" ]]
  then
    echo "Filename is $filename"
  elif [[ "$extension" = "zip" && "$filename" = "file_1.zip" ]] \
  || [[ "$filename" = "file_2.zip" ]] \
  || [[ "$filename" = "file_3.zip" ]]
  then
    echo "Filename is $filename"
  elif [[ "$extension" = "csv" && "$filename" = "two.csv" ]]
  then
    echo "Filename is $filename"
  else
    echo "Filename is $filename"
  fi
done < fileList.txt

致谢!