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

Hi, I have a file which is as follows: <hello.csv> abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 ....... def,8,9,4,5,6 def,5,6,2,1 ....... Could anyone help me to write a command which displays as follows: abc,2,3,4,5,6,7,5,2,1,6,2,3,8,2,1,3,1,4 def,8,9,4,5,6,5,6,2,1
  • Comment on Combining multiple lines based on the given condition

Replies are listed 'Best First'.
Re: Combining multiple lines based on the given condition
by Eily (Monsignor) on Oct 18, 2013 at 19:20 UTC

    The first 13 lines of Text::CSV already show you how to do half the work (there is one extra line though). Except instead of pushing into an array, you have to push the row inside a hash of arrays with the first column has the key.

    push @{ $yourHash{shift @$row} }, @$row # shift returns the first element of an array and deletes it from it

    If you don't know how to uses hashes and hashes of arrays, read perldsc

    Edit: ahem ... square brackets for a hash ... this wouldn't have worked well.

      Could you please help me bit more. Because I'm new to perl. Thanks.
Re: Combining multiple lines based on the given condition
by 2teez (Vicar) on Oct 18, 2013 at 19:31 UTC

    Hi anony,
    Welcome to the Monastery.

    Could anyone help me to write a command which displays as follows..
    How would you solve this yourself? Please check the following: How do I post a question effectively?.
    Ofcourse we are ready to help, but you must show some effort on your part.

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: Combining multiple lines based on the given condition
by Laurent_R (Canon) on Oct 18, 2013 at 21:39 UTC

    It would also be good that you use code tags (<c> and </c>) to show the content of your file as it is really formated (as well as the desired output), since the solution might be different if your file looks like this:

    abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 ....... def,8,9,4,5,6 def,5,6,2,1

    or if it looks like that:

    abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 ....... def,8,9,4,5,6 def,5,6,2,1

    The fact that you don't have commas before the three-letter groups leads me to think that it is more probably the second case, but we can't know for sure.

      Thanks all of you for your replies. Please find the following code.If you have any further changes to this code please let me know .Also, I don't know how to use text::csv , so if anyone could help, it will be nice.

      #!usr/bin/perl use strict; open FH, "/home/test1/hello.csv" or die; my @array,@array1; #----------I'm pushing all abc's and def's data into respective arrays +--------------------------- while(<FH>) { if ($_=~/^abc/) { push(@array,$_); } elsif($_=~/^def/) { push(@array1,$_); } } #----------I'm writing only one for loop for abc, it will be same for +def too. ------------------------------ my @hello; foreach my $i(0..$#array-1) { #-------below code: it splits the second abc and and so on. i.e., stri +ps second abc from the digits.------------------- @hello=split /^\w+\,/,$array[$i+1]; foreach my $j(0..$#hello) { #--------below code:this is for replacing \n of first abc,2,3,4,5,6 wi +th a comma ( ex: abc,2,3,4,5,6, ) $array[$i]=~s/\n/,/g; #--------------below code:here it concatenates the data ( data should +look like: 2,3,4,5,6,7,5,2,1,6,2,3,8,2,1,3,1,4 )---------- abc,$array[$i]=$array[$i].$hello[$j]; print $array[$i],"\n"; } } # In my above code, the data is concatenated as follows: abc,2,3,4,5,6 ,7,5,2,1,6,2,3 ,8,2,1,3,1,4 #But expected output is : abc,2,3,4,5,6,7,5,2,1,6,2,3,8,2,1,3,1,4
        Thank you for attempting to post your code -- but this is not the code you are using. Please use a copy and paste function so we are getting the actual code you are using. There's no point in me debugging a typo on PerlMonks that isn't actually in your code.

        Here's how I know this is not the code you are using:

        C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV>mergetest1.pl Global symbol "@array1" requires explicit package name at C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV\mergetest1.p +l line 5. Global symbol "@array1" requires explicit package name at C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV\mergetest1.p +l line 18. Bareword "abc" not allowed while "strict subs" in use at C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV\mergetest1.p +l line 41. Execution of C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV\mer +getest1.pl aborted due to compilation errors.

        If you don't know how to resolve the errors listed above, ask about those. I would be glad to help you learn this stuff on any level. But I emphasize I will help. This means you have to be there, too.  :-)

        Also, please post your input file (also using a copy and paste function, please), and put it in between

        <readmore>
        <code>
        {your data here}
        </code>
        </readmore>

        tags for easy downloading.

        As noted by Laurent_R, what you posted gives us an idea of what your input data looks like, but it's not quite specific enough given that you ask to help format it exactly like the output you want. Can't get the exact output without the exact input.  :-)

        Finally, once we have your core code working, we will examine the possibility of using the Text::CSVmodule or something similar, and we can cover how you make that happen at that time.

        Let's crawl first, then walk, then run, then, perhaps, even fly.  :-)

        One thing is certain as mentioned by other perlmonks before now that one need know how the OP input file is formatted.
        Please see if the below codes gives some light.
        Using the OP dataset just as was given and using perl split like thus:

        use warnings; use strict; my $l = 'abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 ....... def,8 +,9,4,5,6 def,5,6,2,1 '; my %hash; my $k; for (split/[,. ]+/ => $l){ if(/\D+?/){ $k = $_ }else{ push @{$hash{$k}},$_ } } print $_,',',join (',' => @{$hash{$_}}),$/ for sort keys %hash;
        Secondly, since your input is a CSV file, it is better you use module like Text::CSV or Text::CSV_XS.
        See an example below with a modified OP dataset.
        #!/usr/bin/perl use warnings; use strict; use Text::CSV; use Data::Dumper; my %hash; my $csv = Text::CSV->new( { binary => 1 } ) or die "can't use CSV" . Text::CSV->error_diag(); while ( my $row = $csv->getline(*DATA) ) { push @{ $hash{ shift @$row } }, @$row; # as previously mentioned + by Eily } $csv->eof or $csv->error_diag(); print Dumper \%hash; __DATA__ abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 def,8,9,4,5,6 def,5,6,2,1

        If you tell me, I'll forget.
        If you show me, I'll remember.
        if you involve me, I'll understand.
        --- Author unknown to me
        # In my above code, the data is concatenated as follows: abc,2,3,4,5,6 ,7,5,2,1,6,2,3 ,8,2,1,3,1,4 #But expected output is : abc,2,3,4,5,6,7,5,2,1,6,2,3,8,2,1,3,1,4

        Again, we need to see the input file correctly formatted before we can say for sure what you need to do, but it seems very very likely that your problem comes from the fact that the input is split into separate lines, each of which having a trailing end-of-line character. In this case, you simply need to remove that character from your input lines immediately after you read it (although it could be done later, it is best to do it right away). Change your code as follows:

        while(<FH>) chomp; { # ...

        There are many other things to be said about your code, but this correction should at least solve your immediate problem. I'll wait for a correctly formatted input before making any further comments.

Re: Combining multiple lines based on the given condition
by marinersk (Priest) on Oct 18, 2013 at 20:32 UTC
    Hello anony,

    Could anyone help me to write a command which displays as follows:

    Sure. Show us the code you're using to read the file. Then we can help you with the command needed to merge the data.

Re: Combining multiple lines based on the given condition
by marinersk (Priest) on Oct 20, 2013 at 04:29 UTC
    Okay, in the interest of moving this along, here's a teaser.

    I wrote a Perl script which produces the following output from the following suspected input:

    C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV>type hello.csv abc,2,3,4,5,6 abc,7,5,2,1,6,2,3 abc,8,2,1,3,1,4 def,8,9,4,5,6 def,5,6,2,1 C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV>perl mergetest99 +.pl hello.csv C:\Steve\Dev\PerlMonks\P-2013-10-18@1712-DataMergeCSV>type hello.csv.o +ut.csv abc,2,3,4,5,6,7,5,2,1,6,2,3,8,2,1,3,1,4 def,8,9,4,5,6,5,6,2,1

    If this is what you are looking for and if you want to see how I did this, let's get your code working and I'd be glad to get you moving on this again.

    On the other hand, if this is not what you are looking for, I suppose this demonstrates why you need to post the input file.  :-)