awk: grouping blocks of text of the last word is common in both text files

Viewed 78

I have two file text formatted in this way

1.txt

11
aa
bb

22
dd
ee

2.txt

qq;ww;aa;
qq;zz;bb;

qq;yy;dd;
qq;hh;ee;

enter image description here

I try to obtain a 3.txt file formatted in this way

11
aa
bb
qq;ww;aa;
qq;zz;bb;

22
dd
ee
qq;yy;dd;
qq;hh;ee;

I use this .awk script

awk -f script.awk 2.txt 1.txt

BEGIN{FS=OFS=";"}
{sub(/;$/,"")}
NR==FNR{
    for (i=1;i<=NF;++i)
        for (j=1;j<=NF;++j)
            if (j!=i&&!b[$i,$j]++)
                a[$i,++c[$i]]=$j
    next
}
{
    delete b
    for (i=1;i<=NF;++i)
        ++b[$i]
    for (i=1;i<=NF;++i)
        for (j=1;j<=c[$i];++j)
            if (!b[a[$i,j]]++)
                $(NF+1)=a[$i,j]
    print
}
2 Answers

With your shown samples/attempts only, please try following. Written and tested in GNU awk.

1st solution: This will match each set(from 1.txt and 2.txt)'s last element if they are equal then it will print the sets from both the files eg: (bb from 1.txt is matched with bb; from 2.txt in 1st set(line in case of RS is on paragraph mode) of both the file)

awk -v RS=""  '
FNR==NR{
  arr[FNR]=$0
  next
}
{
  num1=split(arr[FNR],tempArr1,"\n")
  num2=split($0,tempArr2,"\n")
  num3=split(tempArr2[num2],tempArr3,";")
  if(tempArr3[num3-1]==tempArr1[num1]){
    print arr[FNR] ORS $0
  }
}
' 1.txt 2.txt

2nd solution: This considers that values of last lines of each set(from file1 and file2) could be find in anywhere(irrespective of place, like 1st solution specifically compares last position of is equal or not for both file's same set(lines)).

awk -v RS="" '
FNR==NR{
  arr[FNR]=$0
  next
}
{
  num1=split(arr[FNR],tempArr1,"\n")
  num2=split($0,tempArr2,"\n")
  if(index(tempArr2[num2],tempArr1[num1])){
    print arr[FNR] ORS $0
  }
}
' 1.txt 2.txt


NOTE: To run program(taking example of 1st code given above here) in .awk script format, create script.awk script file and make sure it has proper permissions to run:

cat script.awk
FNR==NR{
  arr[FNR]=$0
  next
}
{
  num1=split(arr[FNR],tempArr1,"\n")
  num2=split($0,tempArr2,"\n")
  num3=split(tempArr2[num2],tempArr3,";")
  if(tempArr3[num3-1]==tempArr1[num1]){
    print arr[FNR] ORS $0
  }
}

IN both solutions Run above scipt.awk as follows:

awk -v RS="" -f script.awk 1.txt 2.txt

You could do it by manipulating RS and FS appropriately, e.g.:

combine.awk

# Remember content from 1.txt with $NF as the key
FNR == NR {
  h[$NF] = $0
  next
}

# If the last element in 2.txt is in the hash
$(NF-1) in h {
  print h[$(NF-1)]
  print $0 "\n"
}

Run it like this:

awk -f combine.awk RS= FS='\n' 1.txt FS='[;\n]' 2.txt

Output:

11
aa
bb
qq;ww;aa;
qq;zz;bb;

22
dd
ee
qq;yy;dd;
qq;hh;ee;

Related