难以在 bash 中使用 readlink 将变量和字符串混合到 return 绝对路径

Difficulty using readlink in bash with mix of variables and string to return absolute paths

我有一个配置脚本,用户可以在其中将路径指定为 header 部分中的变量。我希望他们能够使用绝对路径、相对路径和变量(因为这实际上是从另一个 shell 脚本调用的,他们从那里获取变量的值)。在脚本末尾,所有路径都写入文本文件。

我面临的挑战是某些路径中使用的变量可能会在脚本中间发生变化。我在 re-evaluating 获得正确输出的路径上遇到困难。

### HEADER SECTION ###
DIR_PATH="$VAR1/STRING1"
InputDir_DEFAULT="$DIR_PATH/Input"
### END HEADER ###

...some code

if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi

...more code

# $InputDir_DEFAULT needs re-evaluating here
InputDir=$(readlink -m $InputDir_DEFAULT)
echo $InputDir >> $FILE

当我按照上面的方法做的时候遇到了'some condition','echo'的return是$VAR1/STRING1/Input的绝对路径,而我想要的是abs路径$VAR2/STRING2/Input.

下面是一个替代方案,我尝试通过将自身存储为字符串来停止对 InputDir_DEFAULT 进行评估,直到结束。

### HEADER SECTION ###
DIR_PATH="$VAR1/STRING1"
InputDir_DEFAULT='$DIR_PATH/Input' #NOTE: "" marks have changed to ''
### END HEADER ###

if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi

STRING_TMP=$InputDir_DEFAULT
InputDir=$(readlink -m $STRING_TMP)
echo $InputDir >> $FILE

这次 'echo' return 是评估变量和 un-evaluated 字符串的混合:$VAR2/STRING2/$DIR_PATH/Input(对我来说)看起来像 /home/ubuntu/STRING2/$DIR_PATH/Input。只是 $DIR_PATH/ 不应该出现。

这个感觉应该比较直白吧。我希望我走在正确的道路上,这是我对 "" 和 '' 的错误使用。但是我尝试了很多变体都没有成功。

当您初始设置 InputDir_DEFAULT 时,它采用当前设置的值 ${DIR_PATH};即使您稍后更新 ${DIR_PATH}InputDir_DEFAULT 仍将保持之前的设置。要在当前脚本中解决此问题,您可以在 if 语句中再次设置 InputDir_DEFAULT

InputDir_DEFAULT=${DIR_PATH}/Input

此外,在您的第二次尝试中,单引号值设置转换为文字字符串值并且不会扩展为变量值:

InputDir_DEFAULT='$DIR_PATH/Input'

我建议参考 "Quoting" section in the GNU Bash manual

这是我最终得出的解决方案。它混合了@ThatsWhatSheCoded 和其他一些东西的建议,以确保用户不必在 header.

以外的任何地方重新定义变量。

我希望有更优雅的方法来执行此操作,但这确实有效。

### HEADER SECTION ###
DIR_PATH_DEFAULT="$VAR1/STRING1"
InputDir_DEFAULT="$DIR_PATH_DEFAULT/Input"
### END HEADER ###

...some code

if [[ some condition ]]; then DIR_PATH="$VAR2/STRING2"; fi

### Checks whether $DIR_PATH_DEFAULT is used in any variables.
### If so and $DIR_PATH is different, will replace string.
### This will be done for all variables in a list.
if [[ ! "$DIR_PATH_DEFAULT" =~ "$DIR_PATH" ]]; then
    for i in ${!var[@]}; do
        var_def_val=${var[i]}_DEFAULT
        STRING_TMP=${!var_def_val}
        var_def=${var[$i]}_DEFAULT
        if [[ $STRING_TMP == *"$DIR_PATH_DEFAULT"* ]] && [[ ! $var_def == "DIR_PATH_DEFAULT" ]]; then
            STRING_TMP="${STRING_TMP/$DIR_PATH_DEFAULT/$DIR_PATH}"
            eval "${var_def}=$STRING_TMP"
        fi
    done
fi

...more code

InputDir=$(readlink -m $InputDir_DEFAULT)