Perl Script

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • senthilkumars
    New Member
    • Feb 2008
    • 11

    Perl Script

    how to compare two file and update the second file with comparing to first file?
    plz help
  • nithinpes
    Recognized Expert Contributor
    • Dec 2007
    • 410

    #2
    Originally posted by senthilkumars
    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.

    Comment

    • senthilkumars
      New Member
      • Feb 2008
      • 11

      #3
      Originally posted by nithinpes
      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.
      [code=perl]
      #!usr/bin/perl

      open (etcshadow, $ARGV[0]) || die "cannot open: $!";
      open (check, $ARGV[1]) || die "cannot open: $!";
      $newfile="newch eckedfile";
      open (TEXT,">$newfil e") || die "cannot open: $!";
      @personal=<chec k>;
      @etcfile=<etcsh adow>;
      $i=0;

      foreach $personal(@pers onal)
      {
      @persinfo = split(/:/, $personal);

      foreach $etcfile(@etcfi le)
      {
      @etcinfo=split(/:/,$etcfile);
      if($etcinfo[0] =~ m/^$persinfo[0]$/)
      {
      $i=$i+1;
      }
      }
      if($i!=0)
      {
      print TEXT $personal;
      }
      $i=0;
      }
      close(TEXT);
      rename("newchec kedfile",$ARGV[1]);[/code]
      Last edited by numberwhun; Feb 11 '08, 01:43 PM. Reason: add code tags

      Comment

      • nithinpes
        Recognized Expert Contributor
        • Dec 2007
        • 410

        #4
        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:

        [CODE=perl]
        #!usr/bin/perl

        open (etcshadow, $ARGV[0]) || die "cannot open: $!";
        open (check, $ARGV[1]) || die "cannot open: $!";
        $newfile="newch eckedfile";
        open (TEXT,">$newfil e") || die "cannot open: $!";
        @personal=<chec k>;
        @etcfile=<etcsh adow>;
        $i=0;

        foreach $personal(@pers onal)
        {
        @persinfo = split(/:/, $personal);

        foreach $etcfile(@etcfi le)
        {
        @etcinfo=split(/:/,$etcfile);
        if($etcinfo[0] =~ m/^$persinfo[0]$/)
        {
        $i=$i+1;
        }
        if($i!=0)
        {
        print TEXT $etcfile;
        last;
        }
        }
        $i=0;
        }
        close(TEXT);
        rename("newchec kedfile",$ARGV[1]);

        [/CODE]

        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.

        Comment

        • senthilkumars
          New Member
          • Feb 2008
          • 11

          #5
          Originally posted by nithinpes
          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:

          [CODE=perl]
          #!usr/bin/perl

          open (etcshadow, $ARGV[0]) || die "cannot open: $!";
          open (check, $ARGV[1]) || die "cannot open: $!";
          $newfile="newch eckedfile";
          open (TEXT,">$newfil e") || die "cannot open: $!";
          @personal=<chec k>;
          @etcfile=<etcsh adow>;
          $i=0;

          foreach $personal(@pers onal)
          {
          @persinfo = split(/:/, $personal);

          foreach $etcfile(@etcfi le)
          {
          @etcinfo=split(/:/,$etcfile);
          if($etcinfo[0] =~ m/^$persinfo[0]$/)
          {
          $i=$i+1;
          }
          if($i!=0)
          {
          print TEXT $etcfile;
          last;
          }
          }
          $i=0;
          }
          close(TEXT);
          rename("newchec kedfile",$ARGV[1]);

          [/CODE]

          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$$R TqB41oJHFmaKtHK TQzFh1:12922::9 9999::::

          and the second file content like

          karthick:$1$HV DD6786KGDjbscsc c.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$$R TqB41oJHFmaKtHK TQzFh1

          Comment

          • nithinpes
            Recognized Expert Contributor
            • Dec 2007
            • 410

            #6
            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:

            [CODE=text]
            if($i != 0)
            {
            @tempinfo=@pers info;
            ## replace first two elements with that in @etcinfo
            splice(@tempinf o,0,2,($etcinfo[0],$etcinfo[1]));
            $newinfo= join( ':' , @tempinfo);
            print TEXT $newinfo;
            last;
            }
            [/CODE]

            Comment

            • nithinpes
              Recognized Expert Contributor
              • Dec 2007
              • 410

              #7
              Just for the matter of simplicity, you can use the splice function like this:

              [CODE=text]
              splice(@tempinf o,0,2,@etcinfo[0,1]);

              [/CODE]

              Comment

              • Kelicula
                Recognized Expert New Member
                • Jul 2007
                • 176

                #8
                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:
                [code=perl]
                #!/usr/bin/perl

                use strict;
                use warnings;

                use Tie::File;

                my @holder1;
                my @holder2;
                my $i = 0;

                tie my @etcshad, 'Tie::File', "$ARGV[0]" or die "Can't Tile file: $!";
                tie my @check, 'Tie::File', "$ARGV[1]" or die "Can't tie file: $!";

                # I'm not really sure where newcheckedfile is coming from or what it is.
                # Is it a combination of the two files??
                $newfile="newch eckedfile";
                open (TEXT,">$newfil e") || die "cannot open: $!";

                while(<@check>) {
                @holder1 = split(/:/);

                foreach my $e (@etcshad){

                @holder2 = split(/:/, $e);

                if( $holder2[0] =~ /^$holder1[0]$/ ){
                $i++; # This is a shortcut to adding 1 to a number
                }
                if($i){ # 0 is false to perl, anything other than 0 is true.
                # Well except for undef, and "".
                print TEXT $e;
                last;
                }
                }
                $i = 0;
                }


                untie @etcshad;
                untie @check;

                close(TEXT);
                rename("newchec kedfile",$ARGV[1]);
                [/code]


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

                Happy coding!!

                Comment

                • senthilkumars
                  New Member
                  • Feb 2008
                  • 11

                  #9
                  Originally posted by nithinpes
                  Just for the matter of simplicity, you can use the splice function like this:

                  [CODE=text]
                  splice(@tempinf o,0,2,@etcinfo[0,1]);

                  [/CODE]

                  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......

                  Comment

                  Working...