如何从 bash 中的文件打印环境变量(不使用源代码)?

How to print env var from file in bash (without using source)?

许多 shell 脚本,包括 bash 配置文件,只是环境变量设置的列表。 Debian 上的一个这样的脚本是 /etc/os-release,它看起来像这样:

PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

VERSION_CODENAME 对于添加到 apt 源 (/etc/apt/sources.list) 特别有用,例如 Steam to work on ChromeOS。请注意,大多数指令对该值进行硬编码,这可能会导致兼容性问题。

所以我的问题是如何 echo 从文件 /etc/os-release VERSION_CODENAME 的环境变量 使用 source?这很关键,因为我不想为了一次性使用而把我的环境变量弄乱。

这是我知道我现在可以做的,但它在我当前的环境中留下了不希望的变量:

source /etc/os-release && echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main contrib non-free | sudo tee -a /etc/apt/sources.list"

我想也许有一种方法可以启动一个新的(临时的)bash 进程并将变量加载到该环境中。如果没有实际的 shell 脚本,我无法弄清楚这一点。

这里有 4 个不同的答案...

抱歉,方法不止一种;)。您可能会找到很多其他方法,但有最合适的方法(快速、高效、足迹、可读性...)。

1。通过 sed 导入以填充 关联数组 :

declare -A IMPORTED="($(sed < /etc/os-release 's/^\([^=]\+\)=/[]=/'))"

然后

echo ${IMPORTED[VERSION_CODENAME]}
buster

2。提取所需字段(再次使用 sed

AltVersionCodename=$(sed </etc/os-release -ne 's/^VERSION_CODENAME=//p')
echo $AltVersionCodename
buster

3。括号使用他自己的环境下拉到子shell

( . /etc/os-release ; echo $VERSION_CODENAME )
buster

echo $VERSION_CODENAME
 

当前环境不知道$VERSION_CODENAME

4。在没有 forks

的情况下以纯 bash 读取变量文件

由于我们正在处理一个小文件,我们可以使用 循环读取文件,直到找到所需的信息:

while IFS== read varname value;do
    [ "$varname" = "VERSION_CODENAME" ] &&
        ImportedVersionCodename=$value && break
done </etc/os-release
echo $ImportedVersionCodename 
buster

I thought perhaps there is a way to start a new (temporary) bash process and load the variables into that environment.

这就是使用括号创建子 shell 的作用。

(
  . /etc/os-release
  echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main contrib non-free" \
  | sudo tee -a /etc/apt/sources.list
)

...一旦 ) 被击中,您的变量将被删除,因为它们被加载到退出的子 shell 中。

或者像这样使用 readprintf

while read line; do
    name=${line%%=*}
    data=${line#*=}
    printf -v $name "${data//\"}"
done < vars

下一个函数只获取带有键(单引号中的值)的行。

my_set() {
   configfile=""
   key=""
   print -v "$key" $(sed -n "s/^${key}=//p" "${configfile}")
}
my_set /etc/os-release VERSION_CODENAME
echo "deb http://httpredir.debian.org/debian/ $VERSION_CODENAME main.."

当你不需要环境中的var时,使用

my_set2() {
   configfile=""
   key=""
   sed -n "s/^${key}=//p" "${configfile}"
}

echo "deb http://httpredir.debian.org/debian/ $(my_set2 /etc/os-release VERSION_CODENAME) main.."