如何“获取”特定变量

如何“获取”特定变量

假设我有两个 bash 脚本:

提供者.sh,它执行一些过程并需要“暴露” MAP,但不是Aor B

#!/bin/bash
declare -A MAP
A=hello
B=world
MAP[hello]=world

消费者.sh,它执行Provider.sh并需要使用MAP.

#!/bin/bash
source ./Provider.sh
echo ${MAP[hello]}  # >>> world

为了尽可能地整理环境,我希望尽可能少的Provider.sh可见Consumer.sh。如何才能做到只有 MAP 是“来源”的。

答案1

可以使用函数来确定变量的范围。例子:

## Provider.sh
# Global vars
declare -A map

# Wrap the rest of Provider.sh in a function

provider() {

    # Local vars only available in this function
    declare a=hello b=world c d


    # Global vars are available
    map[hello]=world

}

provider "$@"    # Execute function, pass on any positional parameters

# Remove function
unset -f provider

$ cat Consumer.sh
. ./Provider.sh
echo "${map[hello]}"
echo "$a"
$ bash -x Consumer.sh
+ . ./Provider.sh
++ declare -A map
++ provider
++ declare a=hello b=world c d
++ map[hello]=world
++ unset -f provider
+ echo world
world
+ echo ''

答案2

您可以使用函数并使变量成为本地或全局变量:

#!/bin/bash

foo() {
  declare -gA MAP # make global
  local A=hello # make local
  local B=world # make local
  MAP[hello]=world
}

foo

然后:

#!/bin/bash
source ./Provider.sh
[[ -z "$A" ]] && echo "Variable A not defined"
[[ -z "$B" ]] && echo "Variable B not defined"
echo ${MAP[hello]}

输出:

Variable A not defined
Variable B not defined
world

答案3

我不相信有办法只获取 shell 脚本的一部分。你可以选择获取全部内容,也可以什么都不获取。

但是,您可以grep仅从文件中提取所需的行并将其写入新文件,然后您可以获取该新文件。当然,如果您的代码中有一些复杂的函数,那么这将不起作用。

无论如何,最好将此代码拆分为多个脚本,并仅获取您需要的内容。如果您只想使用一个脚本,您还可以将代码放入多个函数中,从多个位置获取代码,然后仅调用您需要的函数。

答案4

当您说source并且有两个文件时,我认为您希望在命令行上提供这两个命令,并希望提供者设置变量供消费者稍后使用。 (啊,我看到消费者来源生产者,所以他们将共享相同的命名空间,消费者不会污染它的调用命名空间。

我对某些 bash_aliases 使用函数,并从.bashrc.这样,它们就可以在当前 shell 中设置和使用变量,而不是在子 shell 中,变量在运行后就会消失。

当我有一个必须获取才能工作的 bash 文件时,我在其中添加了一个提醒shebang

#!/bin/echo "You have to source this file (${BASH_SOURCE}), not run it"
# -*-mode:sh;sh-shell:bash;fill-column:84-*-

请注意,/bin/echo使用的是 /bin/bash,而不是 /bin/bash,这样在运行时,它只会回显第一行。

还将${BASH_SOURCE}向用户提示文件的位置。

第二行# -*-mode:sh;sh-shell:bash;fill-column:84-*-是让 Emacs 在编辑文件时弄清楚如何突出显示和缩进文件。

guest 提供的两个功能很棒,但是如果放在单独的文件中,如果您只是运行文件,则这些功能将不会被激活。

所以,我在这里获取了访客的代码,但进行了一些更改,以实现我认为您可能想要的功能。另外,条件是将它们放入要获取的文件中。

#!/bin/echo "You have to source this file (${BASH_SOURCE}), not run it"
# -*-mode:sh;sh-shell:bash;fill-column:84-*-
# define producer and consumer functions

declare -A MAP  # you might want to use a different name 
                # because this is going to be in your global namespace

function provider() {
    local A=hello
    local B=world
    MAP[hello]=world   
}

## However maybe what you are wanting is a setter function instead?
function providerSetter() {
    MAP[${1}] = ${2}
}

function consumer()
    echo ${MAP[hello]}
}

## Again, you might want a getter function
function consumerGetter()
    echo ${MAP[${1}]}
}

## you can put defaults into the second functions, i.e.,
function providerSetter2() {
    MAP[${1:-hello}] = ${2:-world}
}
function consumerGetter2()
    echo ${MAP[${1:-hello}]}
}

欢迎来到论坛!

相关内容