POSIX shell中的嵌套参数替换

3

在Zsh中,嵌套参数替换是可行的:

$ param=abc

# nested remove prefix ${...#a} and remove suffix ${...%c} =>
$ printf '%s\n' ${${param#a}%c}
# => b

在POSIX中有相应的等价物吗?
$ param=abc
$ printf '%s\n' ${${param#a}%c}
# => dash: 2: Bad substitution
# => sh: ${${param#a}%c}: bad substitution
# => bash: ${${param#a}%c}: bad substitution

2
不,POSIX 中没有相应的功能。每个命令运行一个替换真的很麻烦吗? - Charles Duffy
不是实际上的问题,但由于需要中间值而使用多个命令真的让我的设计感感到困扰。 - benizi
那些不是“命令”。像“A=B”这样的表达式在shell内完全评估,如果您担心性能损失,那么它们几乎没有影响。正如Charles所说,POSIX的Bourne shell根本不支持它,而且它不太可能会支持。我通常使用临时中间变量或eval,具体取决于我的需求。 - Dummy00001
它们是“命令”,在POSIX shell规范的“简单命令”意义上。我不担心性能,我担心程序员的幸福和美学。虽然,担心POSIX兼容性基本上是放弃程序员的幸福。最让人惊讶的是它在bash中没有起作用。 - benizi
2个回答

3
您可以使用expr来提取所需前缀和后缀之间的文本。(当然,这不是嵌套表达式的通用等价物,但可以解决您给出的问题。)
param=abc
expr "$param" : "a\(.*\)c"

表达式 expr 的正则表达式匹配运算符 : 接受两个参数:左参数为字符串,右参数为正则表达式。输出结果是在 \(...\) 组内所匹配到的任何内容。

不错!我经常忘记 expr,而且我不知道它有捕获组。 - benizi
好吧,至少是一个组 :) 如果有多个组,您只会得到第一个组的输出。 - chepner
请注意,expr的“:”运算符的正则表达式隐式地锚定在字符串的开头(即“^a\(.\)c”),因此正则表达式将不会*匹配字符串“1abc”。 - glenn jackman
我从来没有理解为什么存在这种限制。效率问题吗? - chepner

1
Bash不能实现此功能,但有其他一系列工具可完成该任务。
cut -b2 <<< abc
tr -d ac <<< abc
sed s/[ac]// <<< abc
awk '$0=$2' FS= <<< abc

需要注意的是,参数替换不具备可扩展性。 大数据集下参数扩展速度缓慢

printf '4 %s\n' $( ( sed 's/^a(.*)c$/\1/' <<< $param ) ) - imme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接