Shell截取子串时为何移除空白?如何保留前导空白?
为什么前导空白被移除,以及如何保留它?
这问题问到点子上了!咱们先搞明白为啥前导空格没了,再看怎么解决。
原因:Shell的「单词拆分」机制
你用的echo ${line:3}里,变量${line:3}展开后得到的是" D,E,"(开头带空格),但bash在处理未加引号的变量展开时,会触发「单词拆分(Word Splitting)」:
- Shell会把展开后的内容,按照
IFS(内部字段分隔符,默认是空格、制表符、换行符)来分割成多个「单词」 - 前导的空格属于IFS字符,会被当作分隔符直接忽略,剩下的
D,E,被当作单个单词 - 最后
echo命令会把这些单词用单个空格连接输出,自然就看不到前导空格了
解决方法:阻止单词拆分
要保留前导空格,核心就是告诉Shell不要对变量展开结果做单词拆分,有几种靠谱的方式:
1. 给变量展开加双引号(最常用)
给${line:3}套上双引号,Shell就会把整个内容当作一个完整的字符串,不会拆分:
line="C , D,E," echo "Output-`echo "${line:3}"`" # 输出结果:Output- D,E,
或者更推荐用$()代替反引号(嵌套更清晰,可读性更好):
line="C , D,E," echo "Output-$(echo "${line:3}")"
2. 使用printf代替echo
printf对空白的处理比echo更稳定可靠,直接用格式化输出就能保留所有空白:
line="C , D,E," printf "Output-%s\n" "${line:3}" # 输出结果:Output- D,E,
3. 临时修改IFS(不推荐,除非特殊场景)
如果非要用未加引号的变量,可以临时把IFS设为空,这样Shell就不会按空格拆分了,但这种方式容易引发其他问题,一般不建议:
line="C , D,E," OLD_IFS="$IFS" IFS="" echo "Output-`echo ${line:3}`" IFS="$OLD_IFS" # 输出结果:Output- D,E,
内容的提问来源于stack exchange,提问作者Nitish
相关产品推荐
相关产品推荐

