脚本中含空格的Bash变量作为函数参数展开问题
Bash脚本中正确存储带空格参数的函数调用
问题本质
当你把命令和参数存入普通字符串变量后直接执行$CMD时,Bash会执行**分词(Word Splitting)**操作:它会把整个字符串按IFS(默认是空格、制表符、换行符)拆分成多个单词,完全忽略字符串里的引号——因为这些引号此时只是普通字符,不是语法层面的引号。这就是带空格参数被错误拆分的核心原因。
正确解决方案
方法1:使用数组存储命令与参数(推荐)
数组可以完美保留每个参数的边界,不会因空格拆分参数。定义数组时,把函数名和每个参数分别作为数组元素,执行时用"${array[@]}"展开:
#!/bin/bash function tstArgs () { echo "In tstArgs: ArgCnt:$#; Arg1:[$1]; Arg2:[$2]" } # 无空格参数场景 ARG1=today ARG2=tomorrow CMD_ARRAY=(tstArgs "$ARG1" "$ARG2") "${CMD_ARRAY[@]}" # 输出:In tstArgs: ArgCnt:2; Arg1:[today]; Arg2:[tomorrow] # 带空格参数场景 ARGWS1="today with spaces" ARGWS2="tomorrow with spaces" CMD_ARRAY_WS=(tstArgs "$ARGWS1" "$ARGWS2") "${CMD_ARRAY_WS[@]}" # 输出:In tstArgs: ArgCnt:2; Arg1:[today with spaces]; Arg2:[tomorrow with spaces]
方法2:使用eval(谨慎使用)
如果必须用字符串存储,可以结合eval命令,它会重新解析字符串并识别其中的引号语法。注意:若参数包含不可控内容,eval会带来安全风险(比如参数含恶意命令会被执行)。
#!/bin/bash function tstArgs () { echo "In tstArgs: ArgCnt:$#; Arg1:[$1]; Arg2:[$2]" } ARGWS1="today with spaces" ARGWS2="tomorrow with spaces" # 用${VAR@Q}转义参数,生成可被eval正确解析的字符串 CMD_STR="tstArgs ${ARGWS1@Q} ${ARGWS2@Q}" eval "$CMD_STR" # 输出:In tstArgs: ArgCnt:2; Arg1:[today with spaces]; Arg2:[tomorrow with spaces]
${VAR@Q}会把变量内容转义成符合Bash语法的字符串,自动添加必要引号,确保eval解析时不会拆分参数。
为什么你的尝试无效?
- 你用
ARGWS1="'today with spaces'"定义变量时,变量内的单引号是普通字符而非语法引号,$CMD2展开后,Bash会把'today、with、spaces'当成三个独立参数。 - 用数组
ARGARR=($ARGWS1 $ARG2)时,因未加引号,$ARGWS1会被分词拆分,数组实际存储的是'today、with、spaces'、tomorrow,最终CMD3展开后仍会错误拆分参数。
内容的提问来源于stack exchange,提问作者ChrisNY
相关产品推荐
相关产品推荐

