使用 Bash 测试运算符将“if elif fi”转换为“case esac”语句

使用 Bash 测试运算符将“if elif fi”转换为“case esac”语句

我有以下有效的代码:

for file in $(find $1 -maxdepth 10000 -xdev -ignore_readdir_race); do
    if [[ "$file" =~ ^($OP0|$OP1|$OP2|$OP3|$OP4|$OP5|$OP6|$OP7|$OP8|$OP9)$ ]]; then (( SkipCnt++ )) # Count of skipped files
        elif [[ ! -e "$file" ]] ; then (( StalCnt++ ))                      # Count of files that existed last run, but don't now
        elif [[ ! -s "$file" ]] ; then (( ZeroCnt++ ))                      # Count of zero sized files
        elif [[ -d "$file" ]] ; then (( DirCnt++ ))                         # Count of directories
        elif [[ -h "$file" || -L "$file" ]] ; then (( LinkCnt++ ))          # Count of symbolic links
        elif [[ -c "$file" ]] ; then (( CdevCnt++ ))                        # Count of character devices
        elif [[ -b "$file" ]] ; then (( BdevCnt++ ))                        # Count of block devices
        elif [[ -p "$file" ]] ; then (( PipeCnt++ ))                        # Count of pipes
        elif [[ -S "$file" ]] ; then (( SockCnt++ ))                        # Count of sockets
        elif [[ -f "$file" && -s "$file" ]] ; then                          # File must exist, and not be any of the above.

# You can use any one of these three, listed fastest to slowest
            tar -cS --no-recursion --warning=none "$file" &>/dev/null
            # cp --preserve=all --reflink=never "$file" /dev/null
            # cat "$file" 1>/dev/null

            (( FileCnt++ ))                                                 # Count of files cache-loaded
        else
            (( SkipCnt++ ))                                                 # Count of any files not otherwise processed.
    fi

我试图将其转换为 case 语句,但我无法弄清楚...我到目前为止得到的是什么(我只是将每个 if 语句复制到 case 语句中,但它一直引发错误):

错误:

/usr/local/bin/cachewarmup: line 43: syntax error near unexpected token `"$file"'
/usr/local/bin/cachewarmup: line 43: `          [[ "$file" =~ ^($OP0|$OP1|$OP2|$OP3|$OP4|$OP5|$OP6|$OP7|$OP8|$OP9)$ ]]) (( SkipCnt++ ));;'

(不起作用的)代码:

for file in $(find $1 -maxdepth 10000 -xdev -ignore_readdir_race); do
    case true in
            [[ "$file" =~ ^($OP0|$OP1|$OP2|$OP3|$OP4|$OP5|$OP6|$OP7|$OP8|$OP9)$ ]]) (( SkipCnt++ ));;
            [[ ! -e "$file" ]]) (( StalCnt++ ));;
            [[ ! -s "$file" ]]) (( ZeroCnt++ ));;
            [[ -d "$file" ]]) (( DirCnt++ ));;
            [[ -h "$file" || -L "$file" ]]) (( LinkCnt++ ));;
            [[ -c "$file" ]]) (( CdevCnt++ ));;
            [[ -b "$file" ]]) (( BdevCnt++));;
            [[ -p "$file" ]]) (( PipeCnt++));;
            [[ -S "$file" ]]) (( SockCnt++ ));;
            [[ -f "$file" && -s "$file" ]]) tar -cS --no-recursion --warning=none "$file" &>/dev/null; (( FileCnt++ ));;
            *) (( SkipCnt++ ));;
    esac

对我做错的事情有什么想法吗?

答案1

您的案例ifcase

case something in解释为字符串,而something不是命令。something固定的像 这样的字符串true

通常这里会用到变量。它提供一个非固定字符串,用于与代码中稍后出现的模式进行比较。

在你原来的代码逻辑中,没有这样的变量。你的测试是命令(好吧,[[是一个 shell 关键字,严格来说不是命令;但它仍然像命令一样返回退出状态,完全不是字符串)。如果所有命令都尝试将某个变量的值与某些模式进行比较,那么它们可能可以转换为case … esac。在您的命令中,带有 的命令=~执行此操作,但其余的命令执行其他操作。这实际上不符合转换为 的条件case … esac

一般情况下,即使是测试也=~可能或者可能不会符合转换为的条件case … esac。问题是=~使用正则表达式,而的模式case不是正则表达式;通常,可能无法将一种方案严格转换为另一种方案。

坚持if … elif … fi,不要尝试转换为不适合的语法。


更广阔的视野ifcase

if取决于返回退出状态的某些 shell 代码的退出状态。它可能是命令(如grep[)或其他东西(如[[或 管道),像命令一样返回退出状态。基本上在if(或elif)之后,您可以放置随意的shell 代码作为条件。

case直接比较字符串。它不依赖于任何事物的退出状态。虽然原则上你可以将字符串比较(case)转换为实现相同字符串比较的 shell 代码( for if),但转换随意的shell 代码 ( if) 与字符串比较 ( case) 非常麻烦(如果可能的话)。


补充说明

相关内容