bash 中的嵌套变量替换

Nested variable substitution in bash

我在 /etc/bashrc 中发现了 pathmunge() 函数。这很好而且很有用,因为它可以将重复的条目排除在 PATH 之外。

但这也应该是其他变量的模式:CDPATH,LD_LIBRARY_PATH 不应该有重复的条目。所以我尝试以相同的方式编写一个 varmunge 函数。这是:

# varmunge() allows a one and only one addition of entries into the
# a PATH like environment variable. Good use cases for this function
# are: PATH, CDPATH, LD_LIBRARY_PATH
# example: varmunge PATH $HOME/bin [after | before]
#!/bin/sh
varmunge () {
    case "::" in
        *:"":*)
            ;;
        *)
            if [ "" = "after" ] ; then
                export =$:         # These both fail
#                =${}:
            else
                export =:$         # blech.
#                =:${}
            fi
    esac
}

但是,唉,它不起作用。任何人都可以修复我可怜的 bash-ness 吗?

谢谢...

发布正确的 bash 脚本以防其他人可能需要它。

#!/bin/sh
varmunge () {
    case ":${!1}:" in
        *:"":*)
            ;;
        *)
            if [ "" = "after" ] ; then
                eval =${!1}:
            else
                eval =:${!1}
            fi
    esac
}

varprint() {
    echo "=${!1}"
}

# test varprint
VARTEST="path1:path2"
varprint VARTEST

# test varmunge
varmunge VARTEST path1
varmunge VARTEST path1 after
varmunge VARTEST path2
varmunge VARTEST path2 after
varmunge VARTEST path3
varmunge VARTEST path3 after
varmunge VARTEST path3
varmunge VARTEST path4 after
varmunge VARTEST path4

varprint VARTEST

您还没有解释到底是什么不起作用,但这很容易弄清楚(或通过经验测试)。

无论如何,您在这里遇到了两次相同的问题(一旦您尝试变通但未能使用使其起作用的结构)。

你的问题是 </code> 扩展到你试图处理的变量的 <em>name</em> 而不是它的值。</p> <p>因此,当您调用 <code>varmunge PATH /some/path 并且 "::" 行被展开时,您会在您想要 :<value of $PATH>:.

的地方得到 :PATH:

为此,您需要使用(bashism)indirect expansion

所以你想要":${!1}:"那里。

类似地,在您尝试使用 eval indirect assignment 模式的情况下,export 不能那样工作,因此它永远不会重新扩展转义变量名称。

幸运的是,如果你打算使用 export,你不需要这个技巧,因为导出本身就是赋值(类似于 declareprintf -v)。

所以你可以酌情使用export "=${!1}:"export "=:${!1}"

如果您不想不断地重新导出变量,您也可以使用(bashism again)printf -v "" -- %s "${!1}:" 等。