我有两个配置文件,旧的和新的。新的是一个带有默认值的模板配置,可能还有额外的变量。旧是修改后的配置,其值必须保留。我需要做一个新的修改配置:

  • 如果变量在新旧版本中都存在,则保留旧值
  • 如果变量在旧版本中被注释掉,则保留它,反之亦然
  • 如果变量只存在于 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/

    10-16 10:34