http://www.perlmonks.org?node_id=1006696

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

Hi,

I have one file contains list of records. Each field in the record are delimited by ^D character.

I am trying to get each field value by using split function with delimiter as ^D, but it is not giving expected result.

$FileLocation="/home/RND/Sample.txt"; open ($FILE, $FileLocation) or die "$!"; my @arr = <$FILE>; my (@LineDetails); foreach $line (@arr) { @LineDetails = split (/chr(4)/,$line); print $_."\n" foreach ( @LineDetails ); }

Replies are listed 'Best First'.
Re: split a line by control ^D character
by eyepopslikeamosquito (Archbishop) on Dec 02, 2012 at 10:55 UTC

    The problem is that the chr(4) inside your /chr(4)/ regex is not being interpreted as a function call; rather it is being interpreted literally, with the parens in chr(4) being interpreted as regex metacharacters to capture the 4 in a matching chr4, for example!

    There are a number of ways to fix this, for example:

    @LineDetails = split /\04/, $line; # ... or @LineDetails = split chr(4), $line;

      @ eyepopslikeamosquito

      Thanks so much!! It is working fine now.

        You're welcome. One more thing I noticed is that you will probably want to add a line:

        chomp @arr;
        right after my @arr = <$FILE>; to avoid the last field on each line containing a newline.

Re: split a line by control ^D character
by rjt (Curate) on Dec 02, 2012 at 11:38 UTC

    Yes, you definitely want to split on /\x04/ . In addition to that, there are a few places where your code could be cleaned up a little.

    You are declaring @LineDetails outside of your loop. Is there any reason for that? At least in your example, you only use it inside the loop, as a temp variable. You don't actually need the variable at all, to do what you need to do in this example.

    You are sucking the entire file into an array. This can be very memory intensive, depending on the size of the file. It can also cause your program to appear to hang when it is started. Plus, you can eliminate another variable if you read the file line by line.

    I would clean up everything after the open() line as follows:

    use 5.010; # Allow say(). You can use print "$_\n" if you like. ... while (<$FILE>) { chomp; say for split /\x04/; }

    One last thing, as a general security tip, you would be well advised to get used to using the 3 argument open, (i.e., open my $FILE, '<', $FileLocation in your case).

Re: split a line by control ^D character
by karlgoethebier (Abbot) on Dec 02, 2012 at 18:37 UTC
Re: split a line by control ^D character
by rcrews (Novice) on Dec 04, 2012 at 18:29 UTC
    One simple way to do what you're doing is to change the value of Perl's input record separator from an end-of-line to a ^D:
    my $FileLocation = '/home/RND/Sample.txt'; open my $FILE, '<', $FileLocation or die "$!"; my @LineDetails = do { local $/ = chr(4); <$FILE> }; map { print "$_\n" } @LineDetails;

    This eliminates both for loops.

    Note that the foreach keyword is actually a synonym for the for keyword, so in your original post, you can have replaced "foreach" with "for" in both places, which also simplifies your code.