Bash中${variable^^}语法source脚本时失效的问题与解决
${variable^^}语法source执行时报"bad substitution"的问题 我最近碰到一个挺迷惑的问题,跟你分享下我的排查和解决过程:
我在macOS Sierra上通过Homebrew安装了Bash 4.4.12版本,想用${variable^^}这个Bash 4+才支持的语法把变量转大写,写了个测试脚本:
#!/usr/bin/env bash echo $(bash --version) words="test string" uppercase_words=${words^^} echo "words '${words}' uppercased '${uppercase_words}'"
奇怪的现象
- 直接运行脚本(
bash case_test或者./case_test)时一切正常,输出如下:
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
words 'test string' uppercased 'TEST STRING'
- 但用
source case_test执行时,却抛出了bad substitution错误,输出变成:
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin16.3.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
-bash: ${words^^}: bad substitution
words 'test string' uppercased ''
明明两种方式显示的Bash版本一模一样,怎么source就像在用旧版本呢?
原因分析
后来才搞明白:source命令不会理会脚本开头的shebang(#!/usr/bin/env bash)。直接运行脚本时,系统会通过shebang找到Homebrew安装的新版Bash来执行;但source是让当前的登录Shell来解释脚本内容,而我当时的默认Shell还是macOS自带的旧版Bash(3.x版本,不支持${var^^}语法)。脚本里的bash --version调用的是新版Bash,但执行${words^^}的是当前的旧版Shell,所以才会报错。
解决方法
把默认Shell改成Homebrew安装的Bash版本就行:
- 先确认Homebrew安装的Bash路径,通常是
/usr/local/bin/bash(Intel芯片)或者/opt/homebrew/bin/bash(Apple Silicon芯片) - 执行
chsh -s /usr/local/bin/bash(替换成你实际的路径) - 重启终端,之后再用
source case_test执行脚本就正常了
内容的提问来源于stack exchange,提问作者JESii

