AWK输出不一致

时间:2019-06-25 07:59:11

标签: bash awk

我创建了一个bash脚本,该脚本可以在/ etc / environment中追加或覆盖一些现有的环境变量。脚本如下所示:

#!/bin/bash
declare -a array=("http_proxy=http://username:password@proxy:8080"
                  "https_proxy=http://username:password@proxy:8080"
                  "ftp_proxy=ftp://username:password@proxy:8080"
                  "no_proxy=\"localhost, 127.0.0.1\""
                 )

for i in "${array[@]}"; do
        awk -v var="${i%%=*}" '$0 !~ var' /etc/environment > /etc/environment
        echo "$i" >> /etc/environment
done

给出以下输入(/ etc / environment):

http_proxy=http://otheruser:password@otherproxy:8080
https_proxy=http://username:password@proxy:8080
some_env_varible=some_value

我期望以下输出:

http_proxy=http://username:password@proxy:8080
https_proxy=http://username:password@proxy:8080
ftp_proxy=ftp://username:password@proxy:8080
no_proxy="localhost, 127.0.0.1"
some_env_variable=some_value

但是我得到以下输出:

http_proxy=http://username:password@proxy:8080
https_proxy=http://username:password@proxy:8080
ftp_proxy=ftp://username:password@proxy:8080
no_proxy="localhost, 127.0.0.1"

在脚本外部运行awk命令似乎可以正常工作,仅返回与特定环境变量不匹配的行。我很困惑为什么这个脚本无法正常工作。

更新

根据请求:

$ sudo cat /etc/environment
http_proxy=http://username:password@proxy:8080
https_proxy=http://username:password@proxy:8080
ftp_proxy=ftp://username:password@proxy:8080
no_proxy="localhost, 127.0.0.1"
$ i="http_proxy=http://username2:password2@proxy:8080"
$ sudo awk -v var="${i%%=*}" '$0 !~ var' /etc/environment
https_proxy=http://username:password@proxy:8080
ftp_proxy=ftp://username:password@proxy:8080
no_proxy="localhost, 127.0.0.1"

1 个答案:

答案 0 :(得分:4)

您想要实现的目标看起来有些麻烦,您可能需要考虑以下任何一种选择:

更新原始脚本:

您编写的awk行尝试打印文件/etc/environment中没有的所有内容。这正是grep -v所做的:

for i in "${array[@]}"; do
   grep -v "${i%%=*}" /etc/environment > /etc/environment.new
   echo "$i" >> /etc/environment.new
   mv /etc/environment.new /etc/environment
done

利用grep的力量:

现在我们使用grep,您应该知道该标志

  

-f FILE, --file=FILE FILE获取模式,每行一个。空文件包含零个模式,因此不匹配任何内容。

因此,利用流程替换(<(command)),您现在可以执行以下操作:

grep -v -f <(printf "%s\n" "${array[@]}" | cut -d= -f1) -F /etc/environment > /etc/environment.new
printf "%s\n" "${array[@]}" >> /etc/environment.new
mv /etc/environment.new /etc/environment

在这里,我们使用printf "%s\n" "${array[@]}"在新行(cfr bash print array elements on separate lines)上打印数组,并使用cut命令检索=之前的所有内容。

只需使用一个awk

当您想到grepcutawksedtr的组合时,...通常可以将其替换为一个awk。我们将使用awk来读取2个文件。第一个是/etc/environment,第二个是我们可以从printf命令生成的文件。我们将使用aawk数组,其中存储每个key的值,其中key=之前的部分。因此=符号将成为我们的定界符。此外,如果遇到具有相同键的变量,它将被覆盖。这使我们可以用新值更新值。

awk -F'=' '{a[$1]=$0}END{for(i in a) print a[i] }' /etc/environment <(printf "%s\n" "${array[@]}")

如果您在脚本中没有真正使用数组,则可以使用HERE文档来实现相同的目的:

cat - <<EOF awk -F'=' '{a[$1]=$0}END{for(i in a) print a[i] }' /etc/environment -
http_proxy=http://username:password@proxy:8080
https_proxy=http://username:password@proxy:8080
ftp_proxy=ftp://username:password@proxy:8080
no_proxy="localhost, 127.0.0.1"
EOF