简体   繁体   中英

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

Many shell scripts, including the bash profile, are simply lists of environment variable settings. One such script on Debian is /etc/os-release which looks like this:

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/"

The VERSION_CODENAME is particularly useful for adding to apt sources ( /etc/apt/sources.list ) for, say,Steam to work on ChromeOS . Note that most instructions hard-code this value which can cause compatibility problems.

So my question then is how to echo an env var such as VERSION_CODENAME from a file such as /etc/os-release without using source ? That's key because I don't want to clutter up my environment variables with these for a one-time use.

Here's what I know I can do now but it leaves the variables in my current environment which is undesirable:

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

I thought perhaps there is a way to start a new (temporary) bash process and load the variables into that environment. I haven't been able to figure that out without an actual shell script.

4 different answer here...

Sorry, but there is more than one way;). You may found a lot of other ways, but there are the most appropriate (quickness, efficience, footprint, readability...).

1. import through sed to populate associative arrray :

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

Then

echo ${IMPORTED[VERSION_CODENAME]}
buster

2. extract required field (by using sed again)

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

3. parenthesis to drop down to subshell using his own environment

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

echo $VERSION_CODENAME
 

Current environment don't know about $VERSION_CODENAME

4. reading variable file in pure bash, without forks

As we are working on a small file, we could use loop to read the file until required info is found:

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.

That's what using parenthesis to create a subshell does.

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

...as soon as the ) is hit, your variables are removed, as the subshell they were loaded into exits.

Or using read and printf like this:

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

The next function only sources the line with the key (value in single quotes).

my_set() {
   configfile="$1"
   key="$2"
   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.."

When you don't need the var in the environment, use

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM