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

在文件中替换环境变量:awk还是sed?,sed,awk,sh,Sed,Awk,Sh,我在shell脚本中有一个环境变量文件,例如: # This is a comment ONE=1 TWO=2 THREE=THREE # End #!/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 在我的脚本中,我将这个文

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

# This is a comment
ONE=1
TWO=2
THREE=THREE
# End
#!/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
在我的脚本中,我将这个文件(假设它被称为“./vars”)源代码化到当前环境中,并根据用户输入更改(某些)变量。例如:

# This is a comment
ONE=1
TWO=2
THREE=THREE
# End
#!/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
我还有一个名为“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
#!/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
我还有一个名为“configure 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
#!/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的值

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

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

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

不能使用awk并从同一个文件读写(这是问题的一部分)

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

如果您的env文件变得更大,您将看到它在操作系统的缓冲区大小下被截断

另外,不要忘记gawk(大多数Linux安装上的std)有一个内置的阵列环境。你可以从中创造你想要的

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=值可能需要
导出
-ed,以便它们对awk环境数组可见

打印路径的现有值

我希望这有帮助


另外,由于您似乎是新用户,如果您得到的答案有助于您,请记住将其标记为已接受,并/或给它一个+(或-)作为有用的答案。

您不能使用awk并从同一文件读写(这是您的问题的一部分)

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

如果您的env文件变得更大,您将看到它在操作系统的缓冲区大小下被截断

另外,不要忘记gawk(大多数Linux安装上的std)有一个内置的阵列环境。你可以从中创造你想要的

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=值可能需要
导出
-ed,以便它们对awk环境数组可见

打印路径的现有值

我希望这有帮助


另外,当您看起来是新用户时,如果您得到一个有助于您的答案,请记住将其标记为已接受,并/或给它一个+(或-)作为有用的答案。

您只需使用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"
}

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

您只需使用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"
}

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

很抱歉没有说得更清楚。我想将变量从文件读入环境(文件是snippet#1)。然后我想更新环境中的一个或两个变量(更新三个只是一个示例,它可以是任何变量),然后用更新的值重写文件。所以:读,改,写。诀窍是只写回最初在文件中的变量(而不是整个环境)。在原始文件中保留注释会很好。很抱歉没有说得更清楚。我想将变量从文件读入环境(文件是snippet#1)。然后我想更新环境中的一个或两个变量(更新三个只是一个示例,它可以是任何变量),然后用更新的值重写文件。所以:读,改,写。诀窍是只写回最初在文件中的变量(而不是整个环境)。在原始文件中保留评论会很好。谢谢你的尝试,但我想我还没有说清楚。是否有一个sh/sed/awk等价物:perl-ne'/^([^=]+)/;打印“$1=$ENV{$1}\n”?再次感谢。您的编辑似乎更像我想要的,但是ENVIRON[$1]语句没有正确展开。你能再检查一遍吗?谢谢你的尝试,但我想我还是没说清楚。是否有一个sh/sed/awk等价物:perl-ne'/^([^=]+)/;打印“$1=$ENV{$1}\n”?再次感谢。您的编辑似乎更像我想要的,但是ENVIRON[$1]语句没有正确展开。你能再检查一遍吗?谢谢Glenn,这是一个很好的解决方案。我没有想到使用declare。请注意,包括标题(如您的示例中所示)会破坏后续重写配置的调用,但除此之外,这很好。我一直在使用各种
eval
解决方案,直到我读到
declare
。感谢Glenn,这是一个很好的解决方案。我没有想到使用declare。请注意,包括标题(如您的示例中)会破坏后续重写_config的调用,但在其他方面,这是很好的。我一直在使用各种
eval
解决方案,直到我读到关于
declare
的内容。