Bash:即使条件为真也无法进入

Bash: Unable to enter into if even the condition is true

我正在构建一个脚本来备份 WordPress 数据库。 我已经创建了 MySQL 转储所需的函数:

function db_backup {
    read -r -p "Dump the database? [Y/n]: " response
    if [[ $response =~ ^([yY][eE][sS] || [yY])$ ]]
    then
        mysqldump -h  -u  -p  > .sql

        if [[ $? == 0 ]]
        then
            printf "Database %s dumped successfuly in %s.sql\n" ${db_name} ${db_name}
            return 0
        else
            printf "Database backup %bfailed%b\n" ${red} ${reset}
            return 1
        fi  
    else
        return 1
    fi  
}

当 Y 或 Yes/yEs/yeS/YES/yes 被击中时 - 它不会进入 if true 块,并且不会创建转储 :( 数据库详细信息正确并且转储在手边,但我不能进入 IF 条件。

尝试使用 case 语句:

db_backup()
{
    read -r -p "Dump the database? [Y/n]: " response

    case "$response" in
    y|Y|yes|Yes|YES)
        mysqldump -h  -u  -p  > .sql

        if [[ $? == 0 ]]
        then
             printf "Database %s dumpedy in %s.sql\n" ${db_name} ${db_name}
             return 0
        else
             printf "Database backup %bfailed%b\n" ${red} ${reset}
             return 1
        fi
        ;;
    esac
    return 1

}

您的正则表达式匹配(不区分大小写——为格式化目的添加引号)"yes "(尾随 space)或 " y"(前导 space)或空字符串 ""1.

改为这样写:

if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]

甚至更好

if [[ $response =~ ^[yY]([eE][sS])?$ ]]

你也可以使用 globs:

if [[ $response = [yY]?([eE][sS]) ]]

(Bash<4.1 你需要 shopt -s extglob)。您还可以将 response 转换为小写:

if [[ ${response,,} = y?(es) ]]

${var,,} 参数扩展出现在 Bash 4.0)。


1 有趣的是 read(默认为 IFS)去除了前导和尾随 spaces……所以它是不可能与非空字符串匹配。

为什么不先将响应转换为全部大写,然后再与 Y 或 YES 进行比较,例如:

if [[ ${response^^} =~ ^(Y|YES)$ ]]; then ... fi

这样做的好处是你不需要考虑upper/lowercase的可能组合,它们都会被检测到。另外,而不是:

if [[ $? == 0 ]]; then ... fi

你可以这样做:

if [[ $? ]]; then ... fi

对于真值检验,[[ 0 ]]的结果为真,而(( 0 ))的结果为假。

为了可读性考虑一些简化,例如

function db_backup {
    read -r -p "Dump the database? [Y/n]: " response
    if [[ ${response^^} =~ ^(Y|YES)$ ]]
    then
        if mysqldump -h  -u  -p  > .sql
        then
            printf "Database %s dumped successfuly in %s.sql\n" ${db_name} ${db_name}
            return 0
        else
            printf "Database backup %bfailed%b\n" ${red} ${reset}
            return 1
        fi  
    else
        return 1
    fi  
}