2

I have one file (one.cnf) as:

KEY1="value1"
KEY4="VALUE4"

And another file (two.cnf) as:

USER_HOST="local"
KEY1="abc"
PASS="lorem"
KEY2="ABC"
KEY4="XYZ"

I want to read the value for the corresponding variables from one.cnf and replace in two.cnf.
So that the final two.cnf looks like

USER_HOST="local"
KEY1="value1"
PASS="lorem"
KEY2="ABC"
KEY4="VALUE4"
1
  • 1
    Are you sourcing these files in a shell script? In that case, then just source two.cnf before one.cnf.
    – Kusalananda
    Dec 15, 2021 at 14:26

3 Answers 3

6

With awk: read in keys from file one, then replace in file two:

awk 'BEGIN{FS=OFS="="}
     NR==FNR {key[$1]=$2 ; next }
     $1 in key {$2=key[$1]}
     1' one.cnf two.cnf

For replacing, use sponge

awk '<code>' one.cnf two.cnf | sponge two.cnf

Alternatively GNU awk's inplace, but this needs a slight code change to ensure one.cnf is not emptied:

awk -i inplace 'BEGIN{FS=OFS="="}
     NR==FNR {key[$1]=$2}
     FNR!=NR && $1 in key {$2=key[$1]}
     1' one.cnf two.cnf

Use -i inplace -v INPLACE_SUFFIX=.bup for having the original file with .bup-suffix as backup.

2
  • Can tee be used instead of sponge? I think sponge is not available by default in MacOs.
    – MagePsycho
    Dec 15, 2021 at 18:40
  • 1
    @MagePsycho tee would overwrite the file so that is is empty. Simply use a temporary file: awk '..code..' one.cnf two.cnf > temp.cnf && mv temp.cnf two.cnf. After all sponge doesn't really do much more than that.
    – FelixJN
    Dec 15, 2021 at 18:57
2

Assuming you there isn't a slash / character in your key of value in file one, here's one simple way to do that.

while IFS="=" read key value; do sed -i "s/^${key}=.*/${key}=${value}/" two.cnf ; done < one.cnf

One of the problems here is that it will change the file even if the values for some keys are identical in both files. If you want to avoid changing the file for keys that don't need to be changed, you can just add a simple grep:

while IFS="=" read key value; do grep -xq "${key}=${value}" two.cnf || sed -i "s/^${key}=.*/${key}=${value}/" two.cnf ; done < one.cnf

Or without grep and a single sed command:

while IFS="=" read key value; do sed -i "/^${key}=/{/^${key}=${value}$/! s/^${key}=.*/${key}=${value}/}" two.cnf ; done < one.cnf

Other things to notice:

  • If the key from the first file doesn't exist in the second one, it won't be added.
  • I assume the first file ONLY includes line in the form of key=value, and no other types of lines.
  • Also I suggest to backup the second file before the operation in case anything goes wrong.
1
#!/bin/bash           
for val in cat one.cnf          
do       
    KEY=`echo $val | cut -d'=' -f1`     
    VALUE=`echo $val | cut -d'=' -f2`    
    EXISTS=`grep -i "$KEY" two.cnf | grep -v grep`     
    if [ -n "$EXISTS" ]; then       
        VALUE2=`echo "$EXISTS" | cut -d'=' -f2`     
        echo "$VALUE-$VALUE2"                
        sed -i 's/'$VALUE2'/'$VALUE'/g' two.cnf     
    fi      
done

change the file path according to your location.

1
  • It is working .i have highlighted the code. Dec 17, 2021 at 10:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .