我有两个配置文件,旧的和新的。 New 是一个带有默认值和附加变量的模板配置。 Old 是修改后的配置,其中包含必须保留的值。我需要做一个新的修改配置:
- 如果变量在新旧版本中都存在,则保留旧值
- 如果变量在旧版本中被注释掉,则保持不变,反之亦然
- 如果变量只存在于old中,则删除它
- 如果变量只存在于new中,则保留
旧修改
$ cat old.cfg
# var1 = 111
# var2 = 123
var3 = 111
var4 = 123
var5 = 123
新的默认配置
$ cat new_default.cfg
var1 = 111
# var2 = 123
var3 = 111
# var4 = 111
var6 = 111
新修改的配置(期望的)
$ cat new.cfg
# var1 = 111
# var2 = 123
var3 = 111
var4 = 123
var6 = 111
#
总是用空格分隔(因为配置编辑是手动的,我为此使用 sed
:sed -i -E 's/^# ([^ ])/#\1/'
), 所以也许 awk 可以用于整个事情。现在我有这个 awk 'FNR==NR{a[$1]++;next}!a[$1]' new_default.cfg old.cfg
写下变量名(第一列在 awk 中),这对两个文件都是通用的。
============================================= ====
更新: 最后,我使用了下面的答案并对其进行了修改,因此它现在可以更好地满足我的需求,而且看起来更丑陋。
- 接受两个参数,旧配置和补丁配置的模板
- 确保在行首的
#
之后有一个空格 - 确保每个
=
的每一侧都被一个空格包围 - 确保每个实际评论都以两个
#
而不是一个开始 - 发出 awk 命令:如果行以
#
开头 -> 比较第二列; 以##
开头 -> 比较整行;开始时没有#
-> 先比较 专栏
.
#!/bin/bash
for var in "$@"
do
cp $var $var.bak
sed -i -E 's/^#([^ ])/# \1/' $var
sed -i -E 's/(.?)(\s?)=(\s?)(.?)/\1 = \4/' $var
sed -i -E 's/^#([^=]+)$/##\1/' $var
done
awk '{if(/^# /)k=$2;else if(/^## /)k=$0;else k=$1;}NR==FNR{a[k]=$0; next}
{print (k in a)?a[k]:$0}' $1 $2 > output.txt
最佳答案
awk
助您一臂之力!
$ awk '{k=/^#/?$2:$1}
NR==FNR {a[k]=$0; next}
{print (k in a)?a[k]:$0}' config.old config.new
# var1 = 111
# var2 = 123
var3 = 111
var4 = 123
var6 = 111
虽然不确定所有测试都包含在您的示例输入/输出中。
关于bash - 通过有条件地覆盖第二个文件的部分来合并两个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50724942/