tags:

views:

837

answers:

7

I gave up on sed and I've heard it is better in Perl.

I would like a script that can be called from the 'unix' command line and converts DOS line endings CRLF from the input file and replaces them with commas in the output file:

like

myconvert infile > outfile

where infile was:

1
2
3

and would result in outfile:

1,2,3

I would prefer more explicit code with some minimal comments over "the shortest possible solution", so I can learn from it, I have no perl experience.

+7  A: 
#!/bin/perl
while(<>) {      # Read from stdin one line at a time
    s:\r\n:,:g;  # Replace CRLF in current line with comma
    print;       # Write out the new line
}
Dean Povey
thank you :-) this was fast
So it's OK for s/// to operate on $_ implicitly, but not for print to do that?
jrockway
Actually that doesn't quite do what you want, as you have to supply the file on stdin. I'll leave that part as an exercise for the reader.
Dean Povey
Yeah, sorry I didn't read the question properly, I changed it to be correct. I assume that your input file doesn't have a trailing CRLF otherwise this will print 1,2,3
Dean Povey
Err, that should be 1,2,3,
Dean Povey
Its easy to translate this to something that processes a file, and doesn't waste metric tonnes of memory to do its work like the ( currently) accepted answer. +1
Kent Fredric
A: 
use strict;
use warnings;

my $infile = $ARGV[0] or die "$0 Usage:\n\t$0 <input file>\n\n";
open(my $in_fh , '<' , $infile) or die "$0 Error: Couldn't open $infile for reading: $!\n";
my $file_contents;
{

    local $/; # slurp in the entire file. Limit change to $/ to enclosing block.
    $file_contents = <$in_fh>

}
close($in_fh) or die "$0 Error: Couldn't close $infile after reading: $!\n";

# change DOS line endings to commas
$file_contents =~ s/\r\n/,/g;
$file_contents =~ s/,$//; # get rid of last comma

# finally output the resulting string to STDOUT
print $file_contents . "\n";

Your question text and example output were not consistent. If you're converting all line endings to commas, you will end up with an extra comma at the end, from the last line ending. But you example shows only commas between the numbers. I assumed you wanted the code output to match your example and that the question text was incorrect, however if you want the last comma just remove the line with the comment "get rid of last comma".

If any command is not clear, http://perldoc.perl.org/ is your friend (there is a search box at the top right corner).

Offer Kaye
thank you, i just copied it and it works great
thats really wasteful, theres no need to slurp the whole file into memory to do find and replace on it :/
Kent Fredric
A: 

with Perl

$\ = "\n";              # set output record separator
$, = ',';
$/ = "\n\n";

while (<>) {
    chomp;   
    @f = split('\s+', $_);
    print join($,,@f);
}

in unix, you can also use tools such as awk or tr

awk 'BEGIN{OFS=",";RS=""}{$1=$1}1' file

or

tr "\n" "," < file
ghostdog74
if its down voted, please give reasons.
ghostdog74
please do not downvote, but comment
I"m guessing the downvotes are because: 1) It doesn't solve the problem at all like the OP stated ( at least, how i read it ), and 2) it appears to be heavily abusing magic variables in really unobvious ways.
Kent Fredric
i don't mind down voting, but at least inform about what's wrong, so that the solution provider can improve/edit his/her code to correct what is wrong.
ghostdog74
+5  A: 

In shell, you can do it in many ways:

cat input | xargs echo | tr ' ' ,

or

perl -pe 's/\r?\n/,/' input > output

I know you wanted this to be longer, but I don't really see the point of writing multi line script to solve such simple task - simple regexp (in case of perl solution) is fully workable, and it's not something artificially shortened - it's the type of code that I would use on daily basis to solve the issue at hand.

depesz
this seems also a good solution. i did not know it is so simple. i needed comments only for perl syntax, but this is only a regex and 2 switches, no problem with it :-)
+1 the most perlish answer :)
dfa
A: 

Avoid slurping, don't tack on a trailing comma and print out a well-formed text file (all lines must end in newlines):

#!/usr/bin/perl

use strict;
use warnings;

my $line = <>;

while ( 1 ) {
    my $next = <>;
    s{(?:\015\012?|\012)+$}{} for $line, $next;
    if ( length $next ) {
        print $line, q{,};
        $line = $next;
    }
    else {
        print $line, "\n";
        last;
    }
}
__END__
Sinan Ünür
A: 

Personally I would avoid having to look a line ahead (as in Sinar's answer). Sometimes you need to but I have sometimes done things wrong in processing the last line.

use strict;
use warnings;

my $outputcomma = 0;  # No comma before first line

while ( <> )
{
    print ',' if  $outputcomma ;
    $outputcomma = 1 ; # output commas from now on
    s/\r?\n$// ;
    print ;

}
print  "\n" ;
justintime
+1  A: 

It's as simple as:

tr '\n' , <infile >outfile
smoku