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

I have a text file like the one below a|b|c|d|e|f|g|h|i|.... with no end of line delimters present. Now I have to parse it as a,b,c as column headers row 1 to be d e f and so on. Parsing it as a tab delimited file will also do.. I am stuck in the way i need to parse the lines. 1. there are a number of data sets all in a single line- I can use slurp??. 2. Can i identify tis pattern (.*|)3 times and have a \n inserted after that?.

Prefered o/p

a|b|c|
d|e|f|
g|h|i|

Thanks!

Replies are listed 'Best First'.
Re: Parsing a Pipe delimied file
by Eliya (Vicar) on Feb 28, 2012 at 15:31 UTC
    Can i identify tis pattern (.*|)3 times and have a \n inserted after that?

    You haven't mentioned how large the file is.  If it fits into memory, you can read the file into a string and then do

    while ($s =~ /(.*?)\|(.*?)\|(.*?)\|/g) { print "$1\t$2\t$3\n"; }

    or, if you want to keep the pipe symbols as is

    while ($s =~ /((?:.*?\|){3})/g) { print "$1\n"; }

    In case the file is huge, you can do instead

    local $/ = "|"; # set input record separator while (<>) { print $_, scalar <>, scalar <>, "\n"; }

    (requires that you have multiples of 3 number of "...|" items (when using <>) — otherwise you'd have to test for eof in between reading the records)

    Update: or simply use the modulus operator (%) to insert a \n after every 3 records:

    local $/ = "|"; while (<>) { print; print "\n" unless $. % 3; }
Re: Parsing a Pipe delimied file
by LanX (Saint) on Feb 28, 2012 at 15:22 UTC
    you are stuck? what did you try?

    see readline and split for a start.

    Cheers Rolf

Re: Parsing a Pipe delimied file
by Marshall (Canon) on Feb 28, 2012 at 16:19 UTC
    One way...I guess this is one huge line of input..
    #!/usr/bin/perl -w use strict; $/="|"; print $_.<DATA>.<DATA>."\n" while (<DATA>); =prints: a|b|c| d|e|f| g|h|i| =cut __DATA__ a|b|c|d|e|f|g|h|i|
Re: Parsing a Pipe delimied file
by trizen (Hermit) on Feb 28, 2012 at 15:35 UTC
    Something like this?
    my $str = 'a|b|c|d|e|f|g|h|i|'; $str =~ s/(?:.*?\|){3}\K/\n/g; print $str; __END__ a|b|c| d|e|f| g|h|i|
Re: Parsing a Pipe delimied file
by NetWallah (Canon) on Feb 29, 2012 at 04:30 UTC
    This one does not suck the whole file into memory, so can handle large amounts of data:
    use strict; use warnings; local $/="|"; # Record Separator my @buf; while (<DATA>){ #next unless $_=~/\w/; # Ignore Blank ("\n" lines s/\n//; # Zap newlines push @buf,$_; Print_It() if (3==@buf); } Print_It(); #--------------------- sub Print_It{ print join("",@buf),"\n"; @buf=(); } __DATA__ a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r| s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J| K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|1|2| 3|4|5|6|7|8|9|10|11|12|13|14|15|16|17| 18|19|20

                “PHP is a minor evil perpetrated and created by incompetent amateurs, whereas Perl is a great and insidious evil perpetrated by skilled but perverted professionals.”
            ― Jon Ribbens

Re: Parsing a Pipe delimied file
by Anonymous Monk on Feb 29, 2012 at 14:05 UTC
    You can still see the awk influences in Perl.   And for that matter, do not overlook the possibility of using that tool if your purpose is merely to tear-up a file.