Help with splitting up a input file.

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • blazted
    New Member
    • Mar 2007
    • 17

    Help with splitting up a input file.

    I have a text file with a list of servers and then a description of the server along with the applications that may be hosted on them. Here is a example

    Code:
    SERVER01
    SERVER01 Windows Server 2003 RC2. SQL server. Runs blah blah..
    blah. and so forth.
    
    SERVER02
    SERVER02 REDHAT Linux. MAIL etc etc etc
    I am trying to open up the file and parse it into an array that will only list the SERVER Names and then a hash that will have the SERVER name as the key and the description as the hash value.

    I have a start of this and am trying to use a regex expression to at least find and add the servers to the array but this simply input the entire contents of the text file into the array.

    Code:
    sub ParseInputFile(){
    open(SERVERS, "servers.txt") || die "$!";
    @contents=<SERVERS>;
    close(SERVERS);
    
    foreach $server (@contents){
        if($server =~ /\w/){
            my @server_array = (@server_array, $server);
            print "Its added\n";
        }
        
    }
    I figure If I get this done first i can work at then getting it into a hash or maybe even in the same step I can also split it into the hash value as well. But is there any wildcards to use this for PERL? The \w operator matches any word but how do I split my input into words then put the word into a array and then put it into a hash?

    Thanks
  • nithinpes
    Recognized Expert Contributor
    • Dec 2007
    • 410

    #2
    I am modifying your foreach loop to accomplish both tasks.

    [CODE=text]
    foreach $server (@contents){
    chomp $server;
    if($server =~ /^(\w+)\s+(.*)$/) { # grouping first word&remaining words of line
    $sername = $1;
    $desc = $2;
    push @server_array, $sername; # array of server names
    $server_hash{$s ername} = $desc; #hash of server name=>descripti on
    }
    }
    [/CODE]

    To include accidentally introduced space at the begining, you can modify your regex to:
    [CODE=text]
    if($server =~ /^\s*(\w+)\s+(.* )$/)
    [/CODE]

    I am assuming description is not spread over multiple lines.

    Comment

    • blazted
      New Member
      • Mar 2007
      • 17

      #3
      Thanks for the input. Unfortunately the description can be over multiple lines so that is where I am having my main problems. PERL splits each line of the input file into the array which is what is causing me the most problems. There is a blank line between each description.

      I tried your suggestion but it put every word into the array. When I tried removing the chomp operator so I could use whitespace as my end point but this worked better slightly better. But since the whitespace is one or more it thinks that any space in the separation in words is my delimiter character. Is there a way to make the expression 2 or more whitespace?

      Comment

      • eWish
        Recognized Expert Contributor
        • Jul 2007
        • 973

        #4
        As a side note, one thing that will make your script faster is if you read the file line by line rather than slurping the entire file into memory. If you want to slurp the file I would suggest that you use File::Slurp.

        --Kevin

        Comment

        • KevinADC
          Recognized Expert Specialist
          • Jan 2007
          • 4092

          #5
          [CODE=perl]use strict;
          use warnings;
          use Carp;
          my %hash = ();
          my $flag = 0;
          my $desc;
          my $key;
          open(SERVERS, "servers.tx t") or die "$!";
          while(<SERVERS> ){
          chomp;
          if(/^SERVER\d+$/) {# beginning of hash record
          $key = $_;
          $hash{$key} = '';
          $flag = 1;
          next;
          }
          if(/^\s*$/) { # end of hash record
          $hash{$key} = $desc;
          $key = '';
          $flag = 0;
          $desc = '';
          }
          elsif ($flag) {# value of hash record
          $desc .= "$_ ";
          }
          else {# possible unknown condition
          warn "A line I don't know what to do with: $_";
          }
          }
          print "$_ $hash{$_}\n" for sort keys %hash;;
          [/CODE]

          Comment

          • blazted
            New Member
            • Mar 2007
            • 17

            #6
            I got it to work sort of but could not get it to work using a FILEHANDLE. To get my regex correct I simply opened it after assigning a variable to the name of the text file then reading it in. This reads the server name into the hash key and the description as the hash value.

            Code:
            my %hash = ();
            my @array;
            my $file = "servers.txt";
            
            open($file, "<$file");
            
            while (<$file>) {
               last if /^$/;
               my $val = $_;
               $hash{$val} = "";
               push(@array, $_);
            
               while (<$file>) {
                 last if /^$/;
                 $hash{$val} .= $_;
               }
            }
            
            foreach (keys %hash) {
               print "$_$hash{$_}\n";
            
            }
            But I cannot get this to work by using it as a filehandle. I believe this is because of the way it read in with the filehandle.

            Code:
             open(SERVERS, "servers.txt") || die "$!";
                my $contents = "<servers.txt";
                close(SERVERS);
                
                my %hash = ();
                my @array;
                
                while (<$contents>) {
                    last if /^$/;
                    my $desc = $_;
                    $hash{$desc} = "";
                    push(@array, $_);
            
                    while (<$contents>) {
                        last if /^$/;
                        $hash{$desc} .= $_;
                }
                
                foreach (keys %hash) {
                    print "$_$hash{$_}\n";
                }

            Comment

            • KevinADC
              Recognized Expert Specialist
              • Jan 2007
              • 4092

              #7
              Comments removed: I posted in the wrong thread, sorry

              Comment

              • blazted
                New Member
                • Mar 2007
                • 17

                #8
                Never mind I got it. Took me a bit but the problem I was having was the way I was reading the file. I stopped reading it into a array and then searching and simply split it up as it was being read.

                Comment

                • eWish
                  Recognized Expert Contributor
                  • Jul 2007
                  • 973

                  #9
                  The servers.txt is just a file, not a filehandle. The $contents variable is not a filehandle either.

                  [CODE=perl]open(my $FILEHANDLE, '<', $text_file) || die "Can't open file $!\n";
                  while (<$FILEHANDLE> ) {
                  ...do somthing here......
                  }
                  close($FILEHAND LE);[/CODE]

                  perldoc open

                  --Kevin

                  Comment

                  • KevinADC
                    Recognized Expert Specialist
                    • Jan 2007
                    • 4092

                    #10
                    Originally posted by blazted
                    Never mind I got it. Took me a bit but the problem I was having was the way I was reading the file. I stopped reading it into a array and then searching and simply split it up as it was being read.

                    Did you not like the code I posted earlier in the thread or did it not work? You seemed to have ignored it.

                    Comment

                    Working...