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

Hi

I have a text file in the format:

ID1 > 66 ID2 < 7 ID3 between 6 10
These values need to be put into strings in such as way as to be inserted into Oracle. So for example, i would have a string $parameters which would contain ID1|ID2|ID3. A second string would be $operators containing >|<|between. A third string would be $values1 containing 66|7|6, and the final string would be $values2 containing ||10. The $values2 string must contain the same number of fields as the others even if the fields are empty (as above). The text file can be in any order i.e. a between may be on the first line.

I have tried several different ways of building the strings, but always get stuck and lost. For example

while ($line=<TEXTFILE>){ @params = split(/\s/,$line); $id = shift @params; $op = shift @params; $parameters.= $id."|"; $operators .= $op."|"; if ($op eq 'between'){ $v = shift @params; $values1 .= $v.'|'; if ($.>1){ $v2 = shift @params; $values2 .= '|'.$v2; }elsif($.==1){ $v2 = shift @params; $values2 .= $v2.'|'; } $values2 .='|'; $between = 1; } foreach $value (@params){ $values .= $value."|"; } unless ($between){ for (@params){ $v2.='|'; } } }
But this outputs the following:
$parameters = ID1|ID2|ID3 $operators = >|<|between $values1 = 66|7|10 $values2 = 10|
It doesn't loop the required times for $values2 and if a between is in a different place, things really get screwed.

There must be a simpler and cleaner way to do this type of manipulation.

Thanks - sorry for the length!

-----

Eschew obfuscation, espouse elucidation!

Replies are listed 'Best First'.
Re: Building up a string from a text file
by linuxer (Curate) on May 22, 2009 at 14:36 UTC

    Hi, what about this solution:

    #! /usr/bin/perl -l use strict; use warnings; my @parameters; my @operators; my @value1; my @value2; while ( my $line = <DATA> ) { my ( $param, $operator, $value1, $value2 ) = split /\s/, $line; push @parameters, $param; push @operators, $operator; push @value1, $value1; push @value2, defined $value2 ? $value2 : ''; # if $operator is not 'between' $value2 shouldn't be defined, so j +ust add empty string # maybe you want to check $operator additionally } # fill your variables instead of printing print join '|', @parameters; print join '|', @operators; print join '|', @value1; print join '|', @value2; __DATA__ ID1 > 66 ID2 < 7 ID3 between 6 10
Re: Building up a string from a text file
by graff (Chancellor) on May 23, 2009 at 04:03 UTC
    I think you need to get acquainted with "use strict". It might lead you to prefer using fewer variables overall, which would be a good thing. As for the logic in the OP, I'm puzzled. You say the ordering of input lines could be arbitrary, yet you have conditions based on the input line number. Apart from that, the "unless" block at the end is doing something that has no effect on the output: you change the value of $v2 and then don't use the modified value at all.

    Here's a variant similar to the first reply, but with less typing:

    use strict; my @outputs; while (<DATA>) { my @fields = split; push @fields, '' if ( @fields == 3 ); for my $i ( 0..$#fields ) { $outputs[$i] .= $fields[$i] . '|'; } } chop @outputs; # remove final '|'; print "$_\n" for ( @outputs ); __DATA__ ID1 > 66 ID2 between 6 10 ID3 < 7
      Even shorter:
      use strict; my @outputs; while (<DATA>) { my @fields = split; $outputs[$_] .= $fields[$_] . '|' for 0 .. 3; } chop @outputs; # remove final '|'; print "$_\n" for ( @outputs ); __DATA__ ID1 > 66 ID2 between 6 10 ID3 < 7

      CountZero

      A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James