防止PATH变量的复合欺骗

时间:2016-12-10 09:43:40

标签: bash shell sh zsh idempotent

我碰巧使用的是NODE_PATH,我们有这个标准的东西:

NODE_PATH=$NODE_PATH:~/.foo/node_modules

在bash脚本中调用这一行几次,我得到了一堆复合复制,这样NODE_PATH就会被重复项填充。

做出以下事情的最佳方式是什么:

NODE_PATH=$(remove-dupes $NODE_PATH:~/.foo/node_modules)

remove-dubes例程必须知道它的参数是冒号分隔的字符串。

2 个答案:

答案 0 :(得分:1)

if ! grep -q node_modules <<eof
$NODE_PATH
eof
then NODE_PATH=$NODE_PATH:~/.foo/node_modules
fi
  1. 使用当前NODE_PATH执行heredoc:这允许您避免使用管道/子shell

  2. grep -q:这会在第一场比赛后停止grep,并安静输出

  3. !:如果找不到匹配

  4. 执行您的代码

  5. 也很好:

    if awk 'BEGIN {exit ARGV[1] ~ "node_modules"}' "$NODE_PATH"
    then NODE_PATH=$NODE_PATH:~/.foo/node_modules
    fi
    

答案 1 :(得分:1)

我为ksh93编写了一些处理路径类变量的shell函数。这个版本我认为可以在bash(版本4.3?)和ksh93中使用。 nameref变量(typeset -n)的时髦名称是由于Bash不愿意将本地nameref用于与nameref本身具有相同名称的变量(此可能在Bash 4.5版中修复。

function delete_from_path
{
    typeset -n dfp_variable="$1"
    typeset value="$2"

    if [[ "$dfp_variable" == "$value" ]]; then
        variable=""
    else
        dfp_variable="${dfp_variable/#${value}:/}"
        dfp_variable="${dfp_variable/%:${value}/}"
        dfp_variable="${dfp_variable//:${value}:/:}"
    fi
}

function suffix_path
{
    typeset -n sp_variable="$1"
    typeset value="$2"

    if [[ -z "$sp_variable" ]]; then
        sp_variable="$value"
    elif [[ "$sp_variable" != "$value" ]]; then
        delete_from_path sp_variable "$value"
        sp_variable="$( printf '%s:%s' "$sp_variable" "$value" | tr -s ':' )"
    fi
}

function prefix_path
{
    typeset -n pp_variable="$1"
    typeset value="$2"

    if [[ -z "$pp_variable" ]]; then
        pp_variable="$value"
    elif [[ "$pp_variable" != "$value" ]]; then
        delete_from_path pp_variable "$value"
        pp_variable="$( printf '%s:%s' "$value" "$pp_variable" | tr -s ':' )"
    fi
}

function _exists_in_path
{
    typeset -n eip_variable="$1"
    typeset value="$2"

    typeset tmppath="$eip_variable"

    delete_from_path tmppath "$value"

    if [[ "$tmppath" == "$eip_variable" ]]; then
        return 1
    else
        return 0
    fi
}

function consolidate_path
{
    typeset -n cp_variable="$1"

    typeset IFS=':'
    typeset tmpvar
    typeset element

    for element in $cp_variable; do
        if ! _exists_in_path tmpvar "$element"; then
            suffix_path tmpvar "$element"
        fi
    done

    cp_variable="$tmpvar"
}

To&#34;巩固&#34; PATH变量,即要删除所有重复项,可以使用

$ consolidate_path PATH

$HOME/local/bin添加到路径的末尾:

$ suffix_path PATH "$HOME/local/bin"

这适用于所有PATH类变量(值为:的变量 - 分隔路径)。

简单示例:

$ p="a:b:c:b"
$ consolidate_path p
$ echo "$p"
a:b:c

$ suffix_path p "a"
$ echo "$p"
b:c:a

$ delete_from_path p "c"
$ echo "$p"
b:a