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

hello monks.. please excuse the noobie question, i kinda got stuck.. any feedback pointers etc, much appreciated. I currently have a perl script that prints a single command to a TCP Socket
print $sock "$data\r\n"; my @output; $output = join('', @output);
However I now need to process a list of commands (400) to a server, the list is a text file with no delimiters just a new line for each command .. so do I create my array from list?
$data_file = "/path/to/data.txt"; $delimiter = "\n"; open(FILE,"$data_file") || &error('open->data_file',$data_file); @FILE = <FILE>; close(FILE);
ok now the tricky bit.. for me anyway :) do I need to create a long string from the list & split?
$commands = join('',@FILE); @commands = split(/$delimiter/,$commands);
If I get to this position, how can I print the string to my socket? thanks Steve ...

Replies are listed 'Best First'.
Re: print list to socket
by kyle (Abbot) on Jun 05, 2007 at 11:26 UTC

    Do you want a single string that you can print to your socket? You could get that this way:

    chomp @FILE; my $every_command = join '', map { "$_\r\n" } @FILE; print $sock $every_command;

    If you want a list of strings, you could do that this way:

    chomp @FILE; foreach my $command ( @FILE ) { print $sock "$command\r\n"; }

    It might also hep you to look in perlvar at $/, also known as $INPUT_RECORD_SEPARATOR.

      no preference to single string or list.. just the most speedy & efficient way to process list is all I need.. the replies are a great help.. I'm back on track.. :) many thanks!
Re: print list to socket
by Util (Priest) on Jun 05, 2007 at 11:51 UTC

    The newlines in the data file *are* delimiters, of sorts.

    ( ++kyle; he beat me to nearly the same answer, and his is more concise! )

    Untested code:

    use strict; use warnings; my $sock; # ... init socket, etc ... my $data_filename = '/path/to/data.txt'; my $data_delimiter = "\n"; my $sock_line_ending = "\r\n"; open my $data_fh, '<', $data_filename or &error( 'open->data_filename', $data_filename ); my @commands; { local $/ = $data_delimiter; @commands = <$data_fh>; chomp @commands; } close $data_fh or warn "Can't close '$data_filename': $!"; # If nothing needs to happen between commands: #print {$sock} join($sock_line_ending, @commands), # $sock_line_ending; # If something needs to happen between commands: foreach my $command (@commands) { print {$sock} $command, $sock_line_ending; # ... read the response, etc? ... }

Re: print list to socket
by Moron (Curate) on Jun 05, 2007 at 12:26 UTC
    The most popular pre-Perl way to simple record-based manipulations on unix was with sed and awk and Perl retains some sed regexp and quite a few awk features in memoriam, e.g.:
    use English qw( -no_match_vars ); # use awk else at least alpha var names # and disable pre/post-match vars (not needed) # for performance # ... # note: $RS = "\n" is already the default! { local $ORS = "\r\n"; map { chomp; print $sock $_; } <FILE>; }
    (updated thx to points made by johngg)
    __________________________________________________________________________________

    ^M Free your mind!

      Perhaps I'm missing something but I don't think that's going to work. Firstly, shouldn't the file read be outside the map? Seems to be a syntax error with it inside. Secondly, with the read in the right place all that gets passed to the print statement is the result of the chomp so you just pass a series of 1s to the socket. Thirdly, the lines passing through the map are not going to be interpreted as separate records so the lines will all get concatenated with a single "\r\n" at the end.

      Perhaps something along these lines would be better? (I've used "XX" instead of "\r" for visibility).

      use strict; use warnings; print map { chomp; qq{$_ XX\n} } <DATA>; __END__ line 1 line 2 line 3

      and the output

      line 1 XX line 2 XX line 3 XX

      If you do use English; it is a good idea to specify the -no_match_vars option to avoid a performance hit on all regexen in your script.

      # Avoid performance hit on regexen by specifying # -no_match_vars. # use English q{-no_match_vars};

      I hope this is of interest.

      Cheers,

      JohnGG