http://qs321.pair.com?node_id=638403

perl4ever has asked for the wisdom of the Perl Monks concerning the following question:

Ok, I have a file that I need to append different port numbers to the end of each line. File looks like this

Address1= Address2= Address3= Port numbers are generated by pulling them out of another file my $source = "somefile.txt"; my @list; open(IN, "<$source") or die ("Unable to open $source: $!\n"); while(my $line = <IN>) { chomp ($line); $_ = $line; my $line2 = (split)[1]; chomp ($line2); my @words = split(/tcp/, $line2); my $word = $words[0]; chop $word; #print "$word\n"; push @list, $word; } close IN or die "error closing file : $!"; print "$list[0]\n"; print "$list[1]\n"; print "$list[2]\n";
Could someone point me in the right direction on how to do this... I need to be able to open up the file to append, insert the 1st port number from the array above, and so forth:
Address1=$list[0] Address2=$list[1] Address3=$list[2]

Replies are listed 'Best First'.
Re: Need a little help appending lines
by dwm042 (Priest) on Sep 11, 2007 at 20:25 UTC
    I'm going to simplify your input parsing as I think it's a bit confusing. But one way of appending output is:

    #!/usr/bin/perl use warnings; use strict; my $file = "outtest.txt"; open OUT, ">>", $file || die("Cannot open file for output.\n"); my @array; while(<DATA>) { s/tcp//g; @array = split(/\s+/, $_); print OUT "Address1=",$array[1],"\n"; print OUT "Address2=",$array[2],"\n"; print OUT "Address3=",$array[3],"\n"; } __DATA__ tcp 20 tcp 40 tcp 80
    And the output is:

    <code> C:\Code>perl outtest.pl C:\Code>perl outtest.pl C:\Code>type outtest.txt Address1=20 Address2=40 Address3=80 Address1=20 Address2=40 Address3=80
Re: Need a little help appending lines
by johngg (Canon) on Sep 11, 2007 at 21:31 UTC
    Without seeing your "somefile.txt" I'm not sure what you are doing to get your $word. Certainly, the second chomp is superfluous as you can't remove the line terminator twice. My code below is the equivalent of yours except that I don't do the final chop as I can't tell whether it was necessary; it's easy enough to add back in. I perform the parsing of "somefile.txt" in a BEGIN {...} block before going on to append to the lines in the "address" file.

    moritz points out that it can be a bad idea to edit a file in place. Perl does, however, have a handy -i flag for in-place editing which, if given an extension, will preserve your original file with that extension, the modified file taking the original name. Given a spurious "tcp" file and an "address" file

    $ cat spw638403.txt aajkaj XYZtcpHJHKtcpKJHKH ashhgdasjh JKHKJHtcpUUHtcpHDKJHtcpJHDJAHD kjkjn NHYtcpHHGJJH $ cat spw638403.addr Address1= Address2= Address3= $

    running this code (note the -i.bak flag

    #!/usr/bin/perl -i.bak # use strict; use warnings; my @list = (); BEGIN { my $inFile = q{spw638403.txt}; open my $inFH, q{<}, $inFile or die qq{open: $inFile: $!\n}; while ( <$inFH> ) { chomp; push @list, ( split m{tcp}, ( split )[1] )[0]; } close $inFH or die qq{close: $inFile: $!\n}; } while ( <> ) { s{$}{$list[$. - 1]}; print; }

    with the address file as the argument results in the original file preserved as spw638403.addr.bak and the modified file as spw638403.addr

    $ ./spw638403 spw638403.addr $ cat spw638403.addr Address1=XYZ Address2=JKHKJH Address3=NHY $

    I hope this is of use.

    Cheers,

    JohnGG

    Update: Clarified point that the scripts needs the name of the file to be modified as an argument.

    Update 2: Corrected senior moment with flag. It is, of course, the -i flag, not -p

Re: Need a little help appending lines
by moritz (Cardinal) on Sep 11, 2007 at 20:32 UTC
    It's generally a bad idea to edit a file in place.

    What I'd suggest is that you create a new file with the desired content, and the move the new file to the place of the old file.

    You could first read things that you want to append into @list, and then do the "real" operation:

    use File::Copy; # for move() open my $of, '<', $old_file or die "Can't read $old_file: $!"; open my $nf, '>', $new_file or die "Can't write $new_file: $!"; my $line_number = 0; while (my $line = <$of>){ chomp $line; print $nf $line, $list[$line_number]; } close $nf; close $of; move $new_file, $old_file;
      It's generally a bad idea to edit a file in place.

      Is it? Why?

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        It's a bad idea to edit a file in-place without a backup, let's just put it that way. Creating a separate output file from your source means your source *is* the backup. So moritz's point, a little less succinctly put, is, "Don't edit a file with important data unless you can undo any changes."

        (Or use version control.)
Re: Need a little help appending lines
by perl4ever (Novice) on Sep 11, 2007 at 19:19 UTC
    Could I do something like store each line of the file needing to be appended into an array, then do a for, or while loop, and do

    if line in appending file =$line[0], append $list[0], and so on...?

      Certainly, you can read a file into an array, and process that; whether it's a good idea depends on the size of the file. For reasonably sized files (a few megabytes), it's likely to be the choice which uses the least wall-clock time. If the file is very large, something like Tie::File may be appropriate.

      At least until you get the code debugged, I would make sure that you create a backup file when you do an "edit in place."


      editorial corrections


      emc

      Information about American English usage here and here.

      Any New York City or Connecticut area jobs? I'm currently unemployed.

Re: Need a little help appending lines
by naikonta (Curate) on Sep 12, 2007 at 02:32 UTC
    An edit in place with deliberate assumptions on the source file (actually, I get this from dwm042's example):
    $ cat target-file.txt Address1= Address2= Address3= $ perl -Mstrict -pi -wle 'our @ports; BEGIN { my $source = "tcp 20 tcp + 40 tcp 80"; @ports = $source =~ /tcp\s+(\d+)/g;} $_ .= shift(@ports) +;' target-file.txt $ cat target-file.txt Address1=20 Address2=40 Address3=80
    (johngg demonstrates the verbose version of -pi) Or, if you want to keep the original file and redirect the result to other file, you can use -n instead of -p and -i combination. Well, -i.ext keeps the original version with .ext appended to the filename.
    $ cat target-file.txt Address1= Address2= Address3= $ perl -Mstrict -wnle 'our @ports; BEGIN { my $source = "tcp 20 tcp 40 + tcp 80"; @ports = $source =~ /tcp\s+(\d+)/g;} $_ .= shift(@ports); p +rint' target-file.txt > output.txt $ cat output.txt Address1=20 Address2=40 Address3=80 $ cat target-file.txt Address1= Address2= Address3=

    Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

Re: Need a little help appending lines
by Gangabass (Vicar) on Sep 12, 2007 at 06:22 UTC

    I'll try to use Tie::File

    use Tie::File; #.......your code #at this point you have #@ports with port numbers #and file address.txt which you need to append tie @addresses, 'Tie::File', "address.txt" or die $!; for my $position (0..$#ports) { $addresses[$position] .= $ports[$position]; } untie @addresses;

    But you may combine reading of the ports file and updating addresses file (with $. magick).

Re: Need a little help appending lines
by swampyankee (Parson) on Sep 12, 2007 at 14:45 UTC

    If all the lines in your first file look like those in the sample, why not just read the second file (the one with the port numbers) and build the first file from scratch?

    I think some more information about the first file (Address1=, etc) may be in order, as I suspect there is much more to this file than has been revealed.


    emc

    Information about American English usage here and here.

    Any New York City or Connecticut area jobs? I'm currently unemployed.

      There's a lot more to the file where I get the port number from, I just used an example, but here's a more descriptive example of the file I pull the port out of: example.txt:, line from example txt:
      entry_entry_host_entry 8080/tcp # hostname entry entry
Re: Need a little help appending lines
by perl4ever (Novice) on Sep 12, 2007 at 14:33 UTC
    Thank you all very much for your quick help! I'm actually pulling the port numbers out of another file(which is a garbled mess), then wanting to create another file. I know my example is not the best, but the file I get the ports from is very small, as well as the output file. I needed to know how to do this:

    print OUT "Address=",$array[0],"\n";

    Everything is working now, thanks everyone for the cool examples!