在文件中替换环境变量:awk或sed?

时间:2011-05-04 01:33:37

标签: sed awk sh

我有一个环境变量文件,我在shell脚本中提供,例如:

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

在我的脚本中,我将此文件(假设它称为“./vars”)导入当前环境,并根据用户输入更改(某些)变量。例如:

#!/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

正如你所看到的,我一直在尝试使用awk来编写变量,sed也是如此。没有成功。脚本的最后一行失败。有没有办法用awk或sed做到这一点(最好是保留注释,甚至带有'='字符的注释)?或者我应该将'read'与字符串切割结合在一个while循环或其他魔法中?如果可能的话,我想避免使用perl / python并使用Busybox中提供的工具。非常感谢。

编辑:也许用例可能会清楚我的问题是什么。我保留了一个由shell环境变量声明组成的配置文件:

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

我还有一个名为'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

我还有一个名为'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

如何重写配置文件,仅更新配置文件中已存在的变量,最好是保留注释和空行?希望这能把事情搞清楚一点。再次感谢。

3 个答案:

答案 0 :(得分:1)

你不能使用awk并从同一个文件读取和写入(是问题的一部分)。

我更喜欢在重写之前重命名文件(但你可以保存到tmp然后重命名)。

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

如果你的env文件越来越大,你会发现你的操作系统的缓冲区大小被截断了。

另外,不要忘记gawk(大多数Linux安装中的std)都有内置数组ENVIRON。你可以从那里创建你想要的东西

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

当然,您可以获得环境中的所有内容,因此可能比您想要的更多。但可能是一个更好的地方,从你想要完成的事情开始。

修改 最具体的是

   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

编辑2 我认为你的var =值可能需要export -ed所以它们对于awk ENVIRON数组是可见的。

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

打印PATH的现有值。

我希望这会有所帮助。

P.S。因为您似乎是新用户,如果您得到的答案可以帮助您,请记住将其标记为已接受,并且/或者给它一个+(或 - )作为有用的答案。

答案 1 :(得分:0)

我不知道你要做什么,但是如果你想改变变量THREE的值,

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

答案 2 :(得分:0)

您可以使用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"
}

一样使用它
source network.config
# manipulate the variables
rewrite_config network.config

我使用临时文件来尽可能长时间地保持配置文件的存在。