By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,252 Members | 1,346 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,252 IT Pros & Developers. It's quick & easy.

Perl Script

P: 11
how to compare two file and update the second file with comparing to first file?
plz help
Feb 11 '08 #1
Share this Question
Share on Google+
8 Replies


nithinpes
Expert 100+
P: 410
how to compare two file and update the second file with comparing to first file?
plz help
Kindly provide more clarification on your query, what you want to update in second file? Also, post code/part of code that you tried to execute so that someone can tell you where you went wrong.
To compare contents of two files, you can assign file-handles to two arrays and compare elements of these arrays.
Feb 11 '08 #2

P: 11
Kindly provide more clarification on your query, what you want to update in second file? Also, post code/part of code that you tried to execute so that someone can tell you where you went wrong.
To compare contents of two files, you can assign file-handles to two arrays and compare elements of these arrays.
hi i am new to perl. i need to compare to files and make an update if any changes happen in second file, i need to update it in first file. more probably two files are in same format. i use these following code to remove line which are not in etcshadow and present in another file. but i need to update if any word changes in etcshadow and to the new file.
Expand|Select|Wrap|Line Numbers
  1. #!usr/bin/perl
  2.  
  3. open (etcshadow, $ARGV[0]) || die "cannot open: $!";
  4. open (check, $ARGV[1]) || die "cannot open: $!";
  5. $newfile="newcheckedfile";
  6. open (TEXT,">$newfile") || die "cannot open: $!";
  7. @personal=<check>;
  8. @etcfile=<etcshadow>;
  9. $i=0;
  10.  
  11. foreach $personal(@personal)
  12. {
  13. @persinfo = split(/:/, $personal);
  14.  
  15. foreach $etcfile(@etcfile)
  16. {
  17. @etcinfo=split(/:/,$etcfile);
  18. if($etcinfo[0] =~ m/^$persinfo[0]$/)
  19. {
  20. $i=$i+1;
  21. }
  22. }
  23. if($i!=0)
  24. {
  25. print TEXT $personal;
  26. }
  27. $i=0;
  28. }
  29. close(TEXT);
  30. rename("newcheckedfile",$ARGV[1]);
Feb 11 '08 #3

nithinpes
Expert 100+
P: 410
In your script, you are comparing first word of each line . In case, the first word is unique in a file, without any repetition, a small modification in your script should work:

Expand|Select|Wrap|Line Numbers
  1. #!usr/bin/perl
  2.  
  3. open (etcshadow, $ARGV[0]) || die "cannot open: $!";
  4. open (check, $ARGV[1]) || die "cannot open: $!";
  5. $newfile="newcheckedfile";
  6. open (TEXT,">$newfile") || die "cannot open: $!";
  7. @personal=<check>;
  8. @etcfile=<etcshadow>;
  9. $i=0;
  10.  
  11. foreach $personal(@personal)
  12. {
  13. @persinfo = split(/:/, $personal);
  14.  
  15. foreach $etcfile(@etcfile)
  16. {
  17. @etcinfo=split(/:/,$etcfile);
  18. if($etcinfo[0] =~ m/^$persinfo[0]$/)
  19. {
  20. $i=$i+1;
  21. }
  22. if($i!=0)
  23. {
  24. print TEXT $etcfile;
  25. last;
  26. }
  27. }
  28. $i=0;
  29. }
  30. close(TEXT);
  31. rename("newcheckedfile",$ARGV[1]);
  32.  
  33.  
Instead of printing line from second file, I am printing from first file on the condition that it is present in second one. If this is not the case, compare entire string instead of first word.
Feb 11 '08 #4

P: 11
In your script, you are comparing first word of each line . In case, the first word is unique in a file, without any repetition, a small modification in your script should work:

Expand|Select|Wrap|Line Numbers
  1. #!usr/bin/perl
  2.  
  3. open (etcshadow, $ARGV[0]) || die "cannot open: $!";
  4. open (check, $ARGV[1]) || die "cannot open: $!";
  5. $newfile="newcheckedfile";
  6. open (TEXT,">$newfile") || die "cannot open: $!";
  7. @personal=<check>;
  8. @etcfile=<etcshadow>;
  9. $i=0;
  10.  
  11. foreach $personal(@personal)
  12. {
  13. @persinfo = split(/:/, $personal);
  14.  
  15. foreach $etcfile(@etcfile)
  16. {
  17. @etcinfo=split(/:/,$etcfile);
  18. if($etcinfo[0] =~ m/^$persinfo[0]$/)
  19. {
  20. $i=$i+1;
  21. }
  22. if($i!=0)
  23. {
  24. print TEXT $etcfile;
  25. last;
  26. }
  27. }
  28. $i=0;
  29. }
  30. close(TEXT);
  31. rename("newcheckedfile",$ARGV[1]);
  32.  
  33.  
Instead of printing line from second file, I am printing from first file on the condition that it is present in second one. If this is not the case, compare entire string instead of first word.
thanx i got it.but i need to change like this. here i need to update like this
for example original file content like this

karthick:$1$$RTqB41oJHFmaKtHKTQzFh1:12922::99999: :::

and the second file content like

karthick:$1$HVDD6786KGDjbscscc.a0

here while comparing these two file content i need to update only upto
2nd colon starts. ie name followed by ':' and then followed by encrypted
letters ends before 2nd colon. it should update if name(karthick) is same in both file content.
ie i would get like this.
karthick:$1$$RTqB41oJHFmaKtHKTQzFh1
Feb 13 '08 #5

nithinpes
Expert 100+
P: 410
In the case you have to update only first two colon separated fields in each line, you just modify the block where you are printing to new file in the previous script that I posted like below:

Expand|Select|Wrap|Line Numbers
  1. if($i != 0)
  2. {
  3.   @tempinfo=@persinfo; 
  4.  ## replace first two elements with that in @etcinfo
  5.   splice(@tempinfo,0,2,($etcinfo[0],$etcinfo[1])); 
  6.   $newinfo= join( ':' , @tempinfo);
  7.   print TEXT $newinfo;
  8.   last;
  9. }
  10.  
Feb 13 '08 #6

nithinpes
Expert 100+
P: 410
Just for the matter of simplicity, you can use the splice function like this:

Expand|Select|Wrap|Line Numbers
  1.   splice(@tempinfo,0,2,@etcinfo[0,1]); 
  2.  
  3.  
Feb 13 '08 #7

Kelicula
Expert 100+
P: 176
I have found it very useful to "tie" a file in this situation.
That way you can use most of the regular functions that associate with arrays.

See Here

Once the files have been tied to the arrays, you can use: pop, shift, splice, unshift, push etc...

This also reduces overhead because perl doesn't hold the actual file in memory.
It holds special pointers. All changes made to the array are made to the file.

The code could look something like this:
Expand|Select|Wrap|Line Numbers
  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use Tie::File;
  7.  
  8. my @holder1;
  9. my @holder2;
  10. my $i = 0;
  11.  
  12. tie my @etcshad, 'Tie::File', "$ARGV[0]" or die "Can't Tile file: $!";
  13. tie my @check, 'Tie::File', "$ARGV[1]" or die "Can't tie file: $!";
  14.  
  15. # I'm not really sure where newcheckedfile is coming from or what it is.
  16. # Is it a combination of the two files??
  17. $newfile="newcheckedfile";
  18. open (TEXT,">$newfile") || die "cannot open: $!";
  19.  
  20. while(<@check>){
  21. @holder1 = split(/:/);
  22.  
  23.   foreach my $e (@etcshad){
  24.  
  25.   @holder2 = split(/:/, $e);
  26.  
  27.     if( $holder2[0] =~ /^$holder1[0]$/ ){  
  28.      $i++; # This is a shortcut to adding 1 to a number
  29.     }
  30.     if($i){ # 0 is false to perl, anything other than 0 is true.
  31.             # Well except for undef, and "".
  32.     print TEXT $e;
  33.     last;
  34.     }
  35.     }
  36. $i = 0;
  37. }
  38.  
  39.  
  40. untie @etcshad;
  41. untie @check;
  42.  
  43. close(TEXT);
  44. rename("newcheckedfile",$ARGV[1]);
  45.  

I didn't have time to test this code, but you will definitely benefit from reading up on Tie::File.

Happy coding!!
Feb 14 '08 #8

P: 11
Just for the matter of simplicity, you can use the splice function like this:

Expand|Select|Wrap|Line Numbers
  1.   splice(@tempinfo,0,2,@etcinfo[0,1]); 
  2.  
  3.  

thanks. i got exactly which i need. thanks boss, here the output comes in
single line it self.i need a break in it to print it in next line.
Thanks for ur help......
Feb 14 '08 #9

Post your reply

Sign in to post your reply or Sign up for a free account.