开发者

Substituting environment variables in a file: awk or sed?

I have a file of environment variables that I source in shell scripts, for example:

# This is a comment
ONE=1
TWO=2
THREE=THREE
# End

In my scripts, I source this file (assume it's called './vars') into the current environment, and change (some of) the variables based on user input. For example:

#!/bin/sh
# Read variables
source ./vars
# Change a variable
THREE=3
# Write variables back to the file??
awk 'BEGIN{FS="="}{print $1=$$1}' <./vars >./vars

As you can see, I've been experimenting with awk for writing the variables back, sed too. Without success. The last line of the script fails. Is there a way to do this with awk or sed (preferably preserving comments, even comments with the '=' character)? Or should I combine 'read' with string cutting in a while loop or some other magic? If possible, I'd like to avoid perl/python an开发者_JAVA百科d just use the tools available in Busybox. Many thanks.

Edit: perhaps a use case might make clear what my problem is. I keep a configuration file consisting of shell environment variable declarations:

# File: network.config
NETWORK_TYPE=wired
NETWORK_ADDRESS_RESOLUTION=dhcp
NETWORK_ADDRESS=
NETWORK_ADDRESS_MASK=

I also have a script called 'setup-network.sh':

#!/bin/sh
# File: setup-network.sh

# Read configuration
source network.config

# Setup network
NETWORK_DEVICE=none
if [ "$NETWORK_TYPE" == "wired" ]; then
  NETWORK_DEVICE=eth0
fi
if [ "$NETWORK_TYPE" == "wireless" ]; then
  NETWORK_DEVICE=wlan0
fi
ifconfig -i $NETWORK_DEVICE ...etc

I also have a script called 'configure-network.sh':

#!/bin/sh
# File: configure-network.sh

# Read configuration
source network.config

echo "Enter the network connection type:"
echo "  1. Wired network"
echo "  2. Wireless network"
read -p "Type:" -n1 TYPE

if [ "$TYPE" == "1" ]; then
  # Update environment variable
  NETWORK_TYPE=wired
elif [ "$TYPE" == "2" ]; then
  # Update environment variable
  NETWORK_TYPE=wireless
fi

# Rewrite configuration file, substituting the updated value
# of NETWORK_TYPE (and any other updated variables already existing
# in the network.config file), so that later invocations of
# 'setup-network.sh' read the updated configuration.
# TODO

How do I rewrite the configuration file, updating only the variables already existing in the configuration file, preferably leaving comments and empty lines intact? Hope this clears things up a little. Thanks again.


You can't use awk and read and write from the same file (is part of your problem).

I prefer to rename the file before I rewrite (but you can save to a tmp and then rename too).

/bin/mv file file.tmp
awk '.... code ...' file.tmp > file

If your env file gets bigger, you'll see that is is getting truncated at the buffer size of your OS.

Also, don't forget that gawk (the std on most Linux installations) has a built in array ENVIRON. You can create what you want from that

awk 'END {
   for (key in ENVIRON) {
      print key "=" ENVIRON[key]
   }
}' /dev/null

Of course you get everything in your environment, so maybe more than you want. But probably a better place to start with what you are trying to accomplish.

Edit Most specifically

   awk -F"=" '{
     if ($1 in ENVIRON) {
         printf("%s=%s\n", $1, ENVIRON[$1])
     }
     # else line not printed or add code to meet your situation
   }' file > file.tmp
   /bin/mv file.tmp file

Edit 2 I think your var=values might need to be export -ed so they are visible to the awk ENVIRON array.

AND

echo PATH=xxx| awk -F= '{print ENVIRON[$1]}'

prints the existing value of PATH.

I hope this helps.

P.S. as you appear to be a new user, if you get an answer that helps you please remember to mark it as accepted, and/or give it a + (or -) as a useful answer.


I don't exactly know what you are trying to do, but if you are trying to change the value of variable THREE ,

awk -F"=" -vt="$THREE" '$1=="THREE" {$2=t}{print $0>FILENAME}' OFS="=" vars


You can do this in just with bash:

rewrite_config() {
    local filename="$1"
    local tmp=$(mktemp)

    # if you want the header
    echo "# File: $filename" >> "$tmp"

    while IFS='=' read var value; do
        declare -p $var | cut -d ' ' -f 3-
    done < "$filename" >> "$tmp"

    mv "$tmp" "$filename"
}

Use it like

source network.config
# manipulate the variables
rewrite_config network.config

I use a temp file to maintain the existance of the config file for as long as possible.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜