Bash数组含字符串与命令行参数时的空格保留问题
解决Bash数组传递参数给hyperfine的空格拆分问题
问题根源
你的核心问题是错误地给命令字符串添加了额外单引号,以及使用了错误的数组展开方式。hyperfine需要将--prepare等标志和每个待测试命令作为独立参数接收,但你的写法让命令里的选项被当成了hyperfine自身的参数,同时错误的数组展开破坏了参数边界。
正确解决方案
1. 修正命令生成逻辑
不要给生成的命令字符串包裹额外单引号,直接输出原始命令内容:
echo_python() { # 假设command变量已初始化为基础命令(比如"python3 run_whisper.py") command="$command {input_file} --device $device --model $model_name --model_dir $model_directory --output_dir $results_path/output/$device/$contender --output_format json" echo "$command" # 去掉-e,无需额外转义 }
2. 正确构建数组
直接将生成的命令作为数组元素添加,不要加单引号,确保每个--prepare和对应命令的数量匹配:
commands=() # 添加prepare指令(注意:如果有N个测试命令,prepare可以写1次或N次) commands+=(--prepare "use_venv ${top_dir}/original") # 添加测试命令,直接捕获函数输出作为数组元素 commands+=("$(echo_python ${top_dir}/original whisper ${model_path} medium.en $device)") # 如需添加多个测试命令,重复上述步骤 # commands+=("$(echo_python ...)")
3. 正确展开数组
使用"${commands[@]}"展开数组,这会保留每个元素的边界,将每个元素作为独立参数传递给hyperfine:
hyperfine "${commands[@]}"
进阶优化:用数组构建命令(避免字符串拼接问题)
如果命令中有复杂的空格或特殊字符,建议直接用数组构建命令,彻底规避字符串拆分错误:
build_python_command() { local base_cmd="python3 /path/to/your/script.py" # 用数组存储命令的所有部分 local cmd_parts=( "$base_cmd" "{input_file}" "--device" "$device" "--model" "$model_name" "--model_dir" "$model_directory" "--output_dir" "$results_path/output/$device/$contender" "--output_format" "json" ) # 将数组合并为单个字符串输出,保留空格 echo "${cmd_parts[*]}" } # 构建hyperfine参数数组 commands=() commands+=(--prepare "use_venv ${top_dir}/original") commands+=("$(build_python_command)") # 运行基准测试 hyperfine "${commands[@]}"
关键注意点
- 永远用
"${commands[@]}"展开数组,而非"${commands[*]}":前者会将每个数组元素作为独立参数,后者会把所有元素拼接成一个字符串,导致参数边界丢失。 - 不要给测试命令添加额外引号:hyperfine会将每个命令元素作为整体解析,内部空格会被正确保留为命令自身的参数分隔符。
--prepare的数量必须匹配测试命令数量(要么写1次全局生效,要么每个命令对应1次),否则会触发hyperfine的参数校验错误。
内容的提问来源于stack exchange,提问作者Joshua Ferguson
相关产品推荐
相关产品推荐

