Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I want to compare one file with other files in the same directory.

file1.txt contains:

move 34#123#    
get 11#278    
put 33#29#567#23

file1.txt should compare with files 1.txt and 2.txt.

1.txt contains:

move 11    
put 34    
run 13

2.txt contains:

get 14    
move 66

I need the results to be like this:

move 2    
get 1    
put 1

How can I accomplish this?

share|improve this question
    
You want the count of the number of move and get and put lines? –  slm Apr 21 at 6:43
add comment

2 Answers 2

Here is an awk solution:

$ awk 'FNR==NR{a[$1];next}($1 in a){++a[$1]}
    END{for(i in a){print i" "a[i]}}' file1.txt 1.txt 2.txt
put 1
get 1
move 2

Explanation

  • FNR==NR{a[$1];next}: when processing file1.txt, we mark the occurence of $1 in associative array a.
  • ($1 in a){++a[$1]}: when processing 1.txt and 2.txt, we check if $1 is existed in associative array a, if yes, increasing the count by 1.
  • Finally, loop through associative array a, print the key (first field in files) and its value (number of ocurrences in 1.txt and 2.txt).

Here is another solution in perl, with the same logic:

$ perl -alne '++$i;                  
    if ($. == $i) {
        $h{$F[0]}=0;
        close ARGV if eof;
        next;
    }
    ++$h{$F[0]} if defined $h{$F[0]};
END {
    for (keys %h) {
        print $_." ".$h{$_};
    }
}' file1.txt 1.txt 2.txt
move 2
get 1
put 1
share|improve this answer
add comment

Showing an alternative that uses a variety of tools, grep, awk, sort, & uniq. Granted it makes use of more tools but I find it easier to understand what's going on vs. AWK.

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c

Example

$ for i in 1.txt 2.txt; do grep -f <(awk '{print $1}' $i) file1.txt; done | \
    awk '{print $1}' | sort | uniq -c
      1 get
      2 move
      1 put

How it works

Here's the example unrolled a bit.

$ for i in 1.txt 2.txt; do 
    grep -f <(awk '{print $1}' $i) file1.txt
  done | \
    awk '{print $1}' | sort | uniq -c

The for loop goes through the 2 files that we're matching against, 1.txt and 2.txt. Each time through the loop we're using the first column from one of these files as a static set of strings to grep looking for these in our target file, file1.txt. This is the line that does that:

$ grep -f <(awk '{print $1}' $i) file1.txt

After running that using each file from the for loop we take all that output and select only the first column of it:

move
put
move
get

We then use sort and uniq to tally up how many of each type we saw.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.