如何在 Bash 中嵌套用于大写和替换的参数扩展?

How do I nest parameter expansions for uppercasing and substitution in Bash?

我有两个 bash 字符串内置命令,它们独立运行良好,但无论我尝试什么,嵌套时都会生成错误消息。这是两个有效的命令:

$ A="etc/.java"
$ echo $A
/etc/.java
$ B="${A//$'76'/$'7'}"
$ echo $B
/etc/java
$ B="${A^^}"
$ echo $B
/ETC/.JAVA

现在尝试将这两个命令组合在一起时出现错误:

$ B="${${A^^}//$'76'/$'7'}"
bash: ${${A^^}///.//}: bad substitution
$ B="${ ${A^^}//$'76'/$'7'}"
bash: ${ ${A^^}///.//}: bad substitution
$ B="${ ${A^^} //$'76'/$'7'}"
bash: ${ ${A^^} ///.//}: bad substitution
$ B="${"${A^^}"//$'76'/$'7'}"
bash: ${"${A^^}"//'/.'/'/'}: bad substitution
$ B="${ "${A^^}" //$'76'/$'7'}"
bash: ${ "${A^^}" //'/.'/'/'}: bad substitution
$ B="${${A^^} //$'76'/$'7'}"
bash: ${${A^^} ///.//}: bad substitution

上面提供了简化示例,因此您可以复制并粘贴到自己的终端。管道或重定向会很复杂,因为我的真实代码是这样的:

  while [[ $i -lt $DirsArrCnt ]] ; do
    DirsArr[$i]=false
    CurrNdx=$i
    CurrKey="${DirsArr[$(( $i + 1 ))]}"
    # ^^ = convert to upper-case
    # ${Variable//$'16'/$'1'} = Change /. to / for hidden directory sorting
    if [[ "${"${CurrKey^^}"//$'16'/$'1'}" > \
          "${"${LastKey^^}"//$'16'/$'1'}" ]] || \
       [[ "${"${CurrKey^^}"//$'16'/$'1'}" = \
          "${"${LastKey^^}"//$'16'/$'1'}" ]] ; then
        LastNdx=$CurrNdx
        LastKey="$CurrKey"
        i=$(( $i + $OneDirArrCnt))
        continue
    fi

在其中一个扩展是上壳的特殊情况下,可以使用 declare -u(在 Bash 4.0 中引入)在单个扩展中完成。 declare -u 在赋值时转换为大写。

结合大写和替换就变成了这样:

$ declare -u A='/etc/.java'
$ echo "${A//\/./\/}"
/ETC/JAVA

对于小写字母有类似的 -l 和对于标题大小写的(未记录的)-c,但这些是您可以进行 "nested" 参数扩展的唯一情况。