如何通过变量引用修改zsh中原始变量的字符或切片?
Zsh间接变量引用:无需eval修改变量的单个字符/切片
先明确场景:我们有一个标量变量scal,以及存储它名称的引用变量scalRef:
scal='Some value' scalRef=scal
已掌握的间接操作
借助zsh的(P)间接参数扩展标志,已经能实现以下操作:
- 获取原始变量的值、长度、状态、类型:
echo Value: ${(P)scalRef} echo Length State Type: ${(P)#scalRef} ${(P)+scalRef} ${(Pt)scalRef}
- 提取原始变量的单个字符或子串:
echo First char: ${${(P)scalRef}[1]} echo Substring: ${${(P)scalRef}[6,-1]}
- 给原始变量整体赋值:
: ${(P)scalRef::='New value'} echo scal: $scal typeset "${scalRef}"='Other value' echo scal: $scal
问题:修改单个字符/切片的尝试失败
尝试直接修改原始变量的切片时,遇到了问题:
- 写法无报错但不生效:
: ${(P)scalRef[1,5]::='Cool'} echo scal: $scal # 预期输出:Cool value,实际无变化
- 写法报错
no identifier:
: ${${(P)scalRef}[1,5]::='Unknown'} echo scal: $scal # 预期输出:Unknown value,实际报错
解决方案
zsh有两种惯用的无需eval的实现方式:
方案1:利用${:-...}构造完整的间接切片引用
通过${:-$scalRef}展开变量名,再结合(P)标志作用于整个切片表达式:
: ${(P)${:-$scalRef}[1,5]::='Cool'} echo scal: $scal # 输出:Cool value
原理:${:-$scalRef}会被替换为scal,(P)标志让zsh将${:-$scalRef}[1,5]识别为对scal[1,5]的间接引用,从而完成切片赋值。
修改单个字符同样适用:
: ${(P)${:-$scalRef}[1]::='X'} echo scal: $scal # 输出:Xome value
方案2:用typeset拼接修改后的完整值
先通过间接引用获取原始值的切片,替换目标部分后重新赋值:
typeset "${scalRef}"="${${(P)scalRef}[1,5]=Unknown}${${(P)scalRef}[6,-1]}" echo scal: $scal # 输出:Unknown value
原理:${${(P)scalRef}[1,5]=Unknown}会将原始值的前5个字符替换为Unknown,再拼接剩余部分,最后通过typeset赋值给原始变量。
失败原因说明
- 第一种尝试失败:
(P)标志仅作用于scalRef,而非整个scalRef[1,5],zsh无法识别为对原始变量切片的引用。 - 第二种尝试失败:嵌套的参数扩展
${${(P)scalRef}[1,5]}无法作为赋值目标,zsh要求赋值左边必须是明确的标识符。
内容的提问来源于stack exchange,提问作者Hubert Kauker
相关产品推荐
相关产品推荐

