GitHub Actions中含空格的Bash命令无法执行问题排查
我太懂你这个坑了——明明本地跑完全正常的Flutter构建命令,到GitHub Action里就因为参数里的空格报错,简直头大。这本质是Bash参数解析时的引号处理逻辑在搞鬼,咱们一步步拆解问题,给你靠谱的解决方案。
问题根源:引号的「语法意义」vs「字符串内容」
你不管是最初用变量拼接,还是后来尝试的数组写法,都踩了同一个雷:手动添加的双引号被当成了字符串的一部分,而不是Bash用来识别参数边界的语法符号。
比如你生成的APP_NAME="nameOfMyApp preprod",在Bash展开时,它会被拆成三个独立参数:APP_NAME="nameOfMyApp、preprod"——因为空格是默认的分词符,这里的双引号只是普通字符,不会让Bash把整个内容当成一个完整参数。这就导致Flutter把preprod"误判成了要构建的目标文件,自然报错。
正确的数组参数传递方式
解决问题的核心是让Bash明确每个参数的边界,用数组存储独立命令参数是最安全的方式。正确写法应该把--dart-define和对应的键值对作为数组的独立元素:
dart_defines_args=() input="scripts/envs/preprod.env" while IFS='=' read -r name value do # 关键:每个--dart-define和它的键值对作为数组的一组元素 # 这里的双引号是Bash语法,会完整保留value中的空格 dart_defines_args+=(--dart-define "$name=$value") done < "$input" # 执行构建时,必须用双引号包裹数组展开 flutter build apk "${dart_defines_args[@]}"
为什么这样能行?
数组dart_defines_args会把--dart-define和APP_NAME=nameOfMyApp preprod拆成两个独立元素,当你用"${dart_defines_args[@]}"展开时,Bash会把每个数组元素作为单独的命令参数传递给Flutter,最终效果和你在本地手动执行的正确命令完全一致:
flutter build apk --dart-define "APP_NAME=nameOfMyApp preprod" --dart-define "APP_SUFFIX=.preprod"
你之前的数组写法为什么失效?
你之前的代码是把--dart-define 和$name=\"$value\" 作为字符串拼接到数组里,比如:
dart_defines_args+="--dart-define " dart_defines_args+="$name=\"$value\" "
这种写法会让数组里的元素变成一个长字符串:--dart-define APP_NAME="nameOfMyApp preprod" ,当展开数组时,Bash会按空格拆分这个字符串,把APP_NAME="nameOfMyApp和preprod"当成独立参数,自然触发错误。
额外验证小技巧
如果你想确认数组元素是否正确,可以在构建前打印数组的元素个数和每个元素:
echo "数组元素个数:${#dart_defines_args[@]}" for arg in "${dart_defines_args[@]}"; do echo "参数:'$arg'" done
正常情况下,你会看到每个--dart-define和对应的键值对是分开的元素,带空格的参数会被完整显示在单引号里。
内容的提问来源于stack exchange,提问作者Miiite

