Bash脚本含空格参数的引号失效问题:原因分析与解决方法
Bash脚本中带空格参数的引号处理问题
问题重现
执行脚本./testo "two three"时出现错误:
$ ./testo "two three" ls -l "two three_DD_FF" # <- 为何此处查找两个文件? ls: cannot access '"two': No such file or directory ls: cannot access 'three_DD_FF"': No such file or directory
当参数为无空格的two_three时,同样报错:
$ ./testo two_three ls -l "two_three_DD_FF" ls: cannot access '"two_three_DD_FF"': No such file or directory
所用错误脚本代码:
#!/usr/bin/bash cmd="ls -l" trio=""'"'"${1}_DD" trio="${cmd} ${trio}_FF"'"'"" echo ${trio} ${trio}
但直接在命令行执行ls -l "two three_DD_FF"却能正常找到目标文件:
$ ls -l "two three_DD_FF" -rw-rw-r-- 1 myhome me 0 Aug 27 13:09 'two three_DD_FF'
疑问解答
1. 为何相同命令在脚本中执行失败?
Bash的命令解析顺序决定了这一差异:
- 命令行直接执行时:双引号是Shell的语法符号,用来标记单个参数的边界,Shell会解析引号并移除它,将
"two three_DD_FF"作为一个完整参数传递给ls。 - 脚本中通过字符串执行时:当把命令存在字符串变量
trio中再执行${trio},Shell会先对字符串进行单词拆分,此时字符串里的双引号会被当成普通字符,而非语法符号。最终ls收到的参数是"two、three_DD_FF"(带引号的两个独立参数),而非一个完整的文件名。
2. 如何修改脚本以实现正确输出?
不要用字符串存储命令和参数,改用数组保存,这是Bash处理带空格参数的标准方案:
#!/usr/bin/bash # 用数组存储命令及所有参数,每个元素对应一个独立参数 cmd_args=(ls -l "${1}_DD_FF") # 打印命令(用@展开数组,保留参数的独立边界) echo "${cmd_args[@]}" # 执行命令(必须用双引号包裹@展开数组) "${cmd_args[@]}"
原理说明:
数组会将每个元素视为独立的参数单元,"${1}_DD_FF"会被作为一个完整元素存入数组,展开时不会被拆分。执行"${cmd_args[@]}"时,Shell会将数组的每个元素作为独立参数传递给命令,完全符合预期。
内容的提问来源于stack exchange,提问作者udippel
相关产品推荐
相关产品推荐

