Erlo

shell编程技巧——循环逻辑中使用变量引用方式注意事项

2025-09-02 16:29:01 发布   22 浏览  
页面报错/反馈
收藏 点赞

在shell脚本编程中,因为shell脚本的灵活多变与技巧多样性, 我们为了脚本的健壮性,我们经常会定义一些规范,例如变量, 我们一般不用$var, 而用"$var"或"${var}"这种变量引用方式,但是往往它们之间的一些细微差别可能让你的shell脚本产生完全意想不到的的效果. 下面我们通过一个简单的例子来阐述一下.

函数check_invalid_obj主要的功能是在各个PDB数据库中检查无效对象(INVALID OBJECTS), 其中函数get_pdb_list是获取PDB数据库名的列表并赋值给变量$PDB_LIST

check_invalid_obj() {

get_pdb_list

# 检查是否获取到PDB列表
if [ -z "$PDB_LIST" ]; then
    log_error "错误: 未能获取到PDB列表,请检查数据库连接"
    exit ${FAILURE}
fi

# 在每个PDB中执行SQL语句
for pdb_name in  "${PDB_LIST}";
do
    if [ -n "$pdb_name" ]; 
    then
        log_info "正在 $pdb_name 中执行SQL..."
        # 执行SQL语句
        sqlplus -S /nolog 'VALID' order by owner,object_name;
                        exit;
EOF

    fi
done

}

上面这段代码似乎看着没有问题,它跟下面这段代码只有一个地方有细微的区别(循环中变量PDB_LIST的引用方式不同)

check_invalid_obj() {

get_pdb_list

# 检查是否获取到PDB列表
if [ -z "$PDB_LIST" ]; then
    log_error "错误: 未能获取到PDB列表,请检查数据库连接"
    exit ${FAILURE}
fi

# 在每个PDB中执行SQL语句
for pdb_name in  ${PDB_LIST};
do
    if [ -n "$pdb_name" ]; 
    then
        log_info "正在 $pdb_name 中执行SQL..."
        # 执行SQL语句
        sqlplus -S /nolog 'VALID' order by owner,object_name;
                        exit;
EOF

    fi
done

}

如下截图所示(对比着色部分)

这两段代代码,那一段代码才能正常运行呢? 答案是下面这一段代码. 也许只有你自己去调试运行一下,才会明白体会这其中的区别:

  • ${PDB_LIST} 它不保留任何空白或特殊字符,而且分词(word splitting)只发生在无引号的变量
  • "${PDB_LIST}" 它会保留空白/特殊字符, 变量使用双引号方式,会将变量的所有值视为一个整体,导致无法分词(word splitting).

调试运行这两段代码,你就能体会这细微的差别了.具体如下所示(PDB数据库有PDB1,PDB2两个):

错误写法的执行步骤详细信息:

................................................
+ check_invalid_obj
+ get_pdb_list
++ sqlplus -S /nolog
+ PDB_LIST='PDB1
PDB2'
+ '[' -z 'PDB1
PDB2' ']'
+ for pdb_name in "${PDB_LIST}"
+ '[' -n 'PDB1
PDB2' ']'
+ log_info '正在 PDB1
PDB2 中执行SQL...'
+ '[' 1 -eq 1 ']'
+ local 'log_msg=正在 PDB1
PDB2 中执行SQL...'
+ case $LOG_OUT_TYPE in
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:38:27> 正在 PDB1
PDB2 中执行SQL...'
[info]: 20250902 14:38:27> 正在 PDB1
PDB2 中执行SQL...
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:38:27> 正在 PDB1
PDB2 中执行SQL...'
+ sqlplus -S /nolog
                        ALTER SESSION SET CONTAINER="PDB1
                                                    *
ERROR at line 1:
ORA-65000: missing or invalid pluggable database name
........................................................

正确写法的执行步骤详细信息:

+ check_invalid_obj
+ get_pdb_list
++ sqlplus -S /nolog
+ PDB_LIST='PDB1
PDB2'
+ '[' -z 'PDB1
PDB2' ']'
+ for pdb_name in ${PDB_LIST}
+ '[' -n PDB1 ']'
+ log_info '正在 PDB1 中执行SQL...'
+ '[' 1 -eq 1 ']'
+ local 'log_msg=正在 PDB1 中执行SQL...'
+ case $LOG_OUT_TYPE in
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:41:06> 正在 PDB1 中执行SQL...'
[info]: 20250902 14:41:06> 正在 PDB1 中执行SQL...
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:41:06> 正在 PDB1 中执行SQL...'
+ sqlplus -S /nolog

Session altered.


no rows selected

+ for pdb_name in ${PDB_LIST}
+ '[' -n PDB2 ']'
+ log_info '正在 PDB2 中执行SQL...'
+ '[' 1 -eq 1 ']'
+ local 'log_msg=正在 PDB2 中执行SQL...'
+ case $LOG_OUT_TYPE in
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:41:06> 正在 PDB2 中执行SQL...'
++ date '+%Y%m%d %H:%M:%S'
+ echo -e '[info]: 20250902 14:41:06> 正在 PDB2 中执行SQL...'
+ sqlplus -S /nolog
[info]: 20250902 14:41:06> 正在 PDB2 中执行SQL...

Session altered.


no rows selected

扫描上面二维码关注我

如果你真心觉得文章写得不错,而且对你有所帮助,那就不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.

登录查看全部

参与评论

评论留言

还没有评论留言,赶紧来抢楼吧~~

手机查看

返回顶部

给这篇文章打个标签吧~

棒极了 糟糕透顶 好文章 PHP JAVA JS 小程序 Python SEO MySql 确认