关于列表与字符串负索引调用异常的技术咨询
哈哈,这是个典型的Bash数组语法踩坑!你写的li=[1,2,3,4,5]根本不是Bash里数组的正确定义方式——它只是把字符串[1,2,3,4,5]赋值给了变量li而已。当你输入li[-1]时,Bash会把整个表达式当成一个命令去执行,自然会报command not found的错误。
在Bash里,数组的正确打开方式是用空格分隔元素,用圆括号包裹:
li=(1 2 3 4 5)
要取数组的最后一个元素,必须用大括号把变量名包起来,正确语法是${li[-1]}:
echo ${li[-1]} # 输出5,完美拿到最后一个元素
这个语法在Bash 3.0及以上版本都支持,如果你的Bash版本特别老(比如CentOS 6那种古董版),可以用${li[${#li[@]}-1]}来间接获取——${#li[@]}会返回数组的元素总数,减1就是最后一个元素的索引。
首先得澄清:Bash本身根本没有print(str[-1])这种语法——这更像是Python或者其他脚本语言的写法。如果你的环境里这个命令能跑起来,大概率是自定义了print函数,或者不小心混用了其他解释器的语法。
但核心问题其实是:Bash默认是以字节为单位处理字符串的,而中文等非ASCII字符在UTF-8编码下每个字符占3个字节。比如"中国人民"这个字符串,在UTF-8下总共有12个字节(4个汉字×3字节)。
如果用Bash原生的字符串截取语法${str: -1}(注意冒号后面要有空格),取到的只是最后1个字节,这显然不是完整的“民”字。要拿到最后一个完整的汉字,你得按字符而非字节来操作,给你两种实用方法:
- 用
awk处理(前提是系统编码是UTF-8):
str="中国人民" echo "$str" | awk '{print substr($0, length, 1)}'
awk的length函数默认是按字符统计的,所以substr($0, length, 1)就能直接取最后一个字符。
- 用Bash原生语法(需要Bash 4.2+,且编码为UTF-8):
既然每个汉字占3字节,直接取最后3个字节就行:
str="中国人民" echo "${str: -3}" # 输出“民”
至于你为什么得到的是“人”而不是“民”?因为str[-1]取的是最后1个字节,“民”的UTF-8编码是E6 B0 91,最后一个字节91并不是任何完整汉字的编码,你的print函数可能做了错误的字节到字符映射,才显示成了“人”(本质上是乱码的一种表现)。
完全不需要修改系统参数,只要调整字符串处理的逻辑,从字节级切换到字符级操作就可以解决问题。
内容的提问来源于stack exchange,提问作者tanying

