Counting words from one file in another file

Hi All,

I have written a script on this but it does not do the requisite job. My requirement is this:

  1. I have two kinds of files each with different extensions. One set of files are *.dat (6000 unique DAT files all in one directory) and another set *.dic files (6000 unique DIC files in all in the same directory where DAT files are located)

  2. The files only contain words all in new lines. For example:
    1.dat contains something like this"

computer
red
apple
orange

1.dic looks like this:

computer
apple
red
blue
  1. For every corresponding DAT file there is a DIC file. For 1.dat, I have 1.dic, 2.dat and 2.dic .......6000.dat and 6000.dic

  2. What I want to do is to read every word from DIC files and search in the corresponding DAT file and find the number of times the word appears in the .dat file and write the result in .cnt file with the same number. For example:
    1.dic contains 10 words, I read every word from 1.dic line by line and search in 1.dat as to how many times each word from 1.dic appears in 1.dat. Then I write the result (i.e. count values) in every line in 1.cnt. Similarly, I read every word in 2.dic line by line, search words in 2.dat and write the count values in 2.cnt. My 2.cnt should look something like this

2
3
1
3

i.e word in the first line (of 2.dic) appears 2 times in 2.dat. Same thing has to be done with all the 6000 files.

What I have done so far:

ls -1 *.dat | while read page
do
  ls -l *.dic | while read page1
    cat $page1 | while read var1
    do
      grep -c $var1 $page > $page.cnt
    done
  done
done

Untested:

awk 'END { out() }
FNR == 1 {
  NR > 1 && out() 
  fn = FILENAME; split(x, w)
  sub(/.dic$/, x, fn); c = x
  dn = fn ".dat"; on = fn ".cnt"
  }
{  w[$0]; p[++c] = $0 } 
func out() {
  while ((getline dat < dn) > 0)
    dat in w && w[dat]++
  for (i = 0; ++i <= c;)
    printf "%d\n", w[p] > on
  close(on)
  }  
  ' *dic
1 Like

Also untested, but pretty near :slight_smile:

for DAT in *.dat
do
CNT="`basename $DAT .dat`".cnt
DIC="`basename $DAT .dat`".dic
awk 'NR==FNR{dic[$1]++; next}dic[$1]{cnt[$1]++}END{ for(c in cnt) print cnt[c]; }' $DIC $DAT > $CNT
done
1 Like

citaylor's solution gets the counts but outputs them in the wrong order.

This fixes (tested)

for DAT in *.dat
do
CNT=$(basename "$DAT" .dat).cnt
DIC=$(basename "$DAT" .dat).dic
awk 'NR==FNR{dic[$1]=r++; cnt[r]=0; next}
   $1 in dic{cnt[dic[$1]]++} 
   END{for(i=0;i<r;i++) print cnt}' $DIC $DAT > $CNT 
done
1 Like

Hi All,

Thanks for your replies.

Using some of the code above I have come up with a solution of my own to another problem using the same set of files.

What I want to do is to read every word from DIC files and search in "ALL" DAT files and find the "number" of DAT files that contain that word from the DIC file and store the result in FIL files. This means I have to only count once in the DAT files even if that word appears several times in that DAT file. For example:
1.dic contains 10 words, I read every word from 1.dic line by line and search in all DAT files as to how many DAT files contain that word from 1.dic. Then I write the result (i.e. count values) in every line in 1.fil. Similarly, I read every word in 2.dic line by line, search words in all DAT files and write the count values in 2.fil. My 2.fil should look something like this:

20
32
1
3

i.e word in the first line (of 2.dic) appears 20 times in all the DAT files (counting that word only once in all DAT files even if one DAT file contains that word several times). Same thing has to be done with all the 6000 DIC files.

for DAT in *.dat
do
for DIC in *.dic
do
while read word
CNT=$(basename "$DAT" .dat).fil
DIC=$(basename "$DAT" .dat).dic
grep -il "$word" | find . | wc -l $DIC $DAT > $FIL
done
done

How about something like this:

for DIC in *.dic
do
    FIL=$(basename "$DIC" .dic).fil
    ls *.dat | awk '
       NR==FNR {dic[$1]=r++; cnt[r]=0; next}
       { FILE=$0
         while((getline < FILE))
             if($1 in dic && !($1 in fnd)) {
                 fnd[$1]++;
                 cnt[dic[$1]]++;
             }
         delete fnd
       }
       END {for(i=0;i<r;i++) print cnt}' $DIC - > $FIL
done
1 Like