Merge two files by condition

I have two files as below
A file

/* comment for id1 */
"id1" = "x1"

/* comment for id2 */
"id2" = "x2"

/* comment for id3 */
"id3" = "x3"

B file

/* comment for id1 */
"id1" = "y1"

/* comment for id2 */
"id2" = "x2"

I hope output file as below

/* comment for id1 */
"id1" = "y1"

/* comment for id2 */
"id2" = "x2"

/* comment for id3 */
"id3" = "x3"

Condition looks like

  1. All comment lines in A file will output
  2. if same comment line in B file, line below that comment line in B file will output
  3. if no same comment line in B file, line below comment line in A file will output

Does anyone help me?

awk 'NR==FNR && /^\/\*/{getline m;a[$0]=m; next;} /^\/\*/{getline n;b[$0]=n;}
 END{ for (i in a){
 if( i in b){ print i"\n"b; }else
 print i"\n"a;
 }}' file1 file2


Hi mikezang,

One way:

$ awk '
    FNR == NR && $0 ~ /^\/\*/ { 
        getline codeB; 
        comments[ $0 ] = codeB; 
        next; 
    } 

    $0 ~ /^\/\*/ { 
        if ( $0 in comments ) { 
            codeA = comments[ $0 ]; 
        } 
        else { 
            getline codeA; 
        } 
        printf "%s\n%s\n", $0, codeA;
        next;
    }

    FNR < NR && /^[[:space:]]*$/
' fileB fileA
/* comment for id1 */
"id1" = "y1"

/* comment for id2 */
"id2" = "x2"

/* comment for id3 */
"id3" = "x3"

A bit shorter:

awk 'NR==FNR&&/^\/\*/{x=$0;getline;a[x]=$0;next}/^\/\*/{x=$0;print;getline;$0=a[x]?a[x]:$0;printf $0"\n\n"}' B A
1 Like
awk 'FNR==NR{if($0 ~ /^\//){a[$4]=$0}else{a[$1]=$3};next}{
if($0 ~ /^\//){print a[$4]?a[$4]:$0}else{if(a[$1] != $3){print $1,$2,a[$1]?a[$1]:$3}else{print $0}}}' file2 file1
1 Like
awk 'NR==FNR{if (!/^\/\*/) A[$1]=$3; next} $1 in A && !/^\/\*/{$3=A[$1]}1' B A
1 Like

Thanks for your shorter answer!
If I want to output to file B, what can I do?

---------- Post updated at 04:08 ---------- Previous update was at 04:07 ----------

Thanks for your shortest answer, How can I output to B file?

You can append > C to write the output to file "C"

Hi bartus11 and Scrutinizer
I tried both of yours, but no output, why?

By the way, the order of lines might be different. for example
A File like this

/* comment for id1 */
"id1" = "x1"

/* comment for id3 */
"id3" = "x3"

/* comment for id2 */
"id2" = "x2"

---------- Post updated at 04:49 ---------- Previous update was at 04:36 ----------

Did you make a mistake? do you think need for last "1"?

awk 'NR==FNR{if (!/^\/\*/) A[$1]=$3; next} $1 in A && !/^\/\*/{$3=A[$1]}1' B A

You can't do that directly for reasons explained here.

I hope this helps.

bakunin

Are you by any chance running this code on Solaris?

Sorry, I only have chance to run it on Mac..

Which errors you are getting..?

No error, but no output..

Have you tried all other solutions..?

It seems like you a are doing some typo mistake while running.

What OS and version are you using?

Can you test it for me?
I test it a below, but no any output, I hope that I can get result as output.txt

awk 'NR==FNR&&/^\/\*/{x=$0;getline;a[x]=$0;next}/^\/\*/{x=$0;print;getline;$0=a[x]?a[x]:$0;printf $0"\n\n"}' old.txt new.txt

Mac OS X 10.8 Mountain Lion

After looking at your given input files and given dummy files. there is huge difference in it.

But it is working fine on my machine and giving output also.( although it has some junk characters in it)
It seems there is problem with your machine only.

This is what i got..

/* Class = "IBUILabel"; text = "Localized in Localizable.strings"; ObjectID = "Zj6-dJ-hY4"; */
"AyO-ff-rBb.text" = "MainStoryboard_iPhone.strings?????????";

/* Class = "IBUIButton"; normalTitle = "Button"; ObjectID = "LyY-6Q-CCh"; */
"LyY-6Q-CCh.normalTitle" = "Button";

/* Class = "IBUILabel"; text = "Localized in Localizable.strings"; ObjectID = "Zj6-dJ-hY4"; */
"MZF-J3-zXE.text" = "??Storyboard????";

/* Class = "IBUILabel"; text = "Localized in Localizable.strings"; ObjectID = "Zj6-dJ-hY4"; */
"Zj6-dJ-hY4.text" = "Localized in Localizable.strings";

If you can do it, I think my os is Mac, so the same script can't do them same thing, what can I do next?