Question

I wrote this code and it works fine, it should find lines in which there's no string like 'SID' and append a pipe | at the beginning of the line, so like this: find all lines in which there's no 'SID' and append a pipe | at the beginning of the line. But how I wrote it, I can just output the lines which were changed and have a pipe. What I actually want: leave the file as it is and just append the pipes to the lines which match. Thank you.

#!usr/bin/perl
use strict;
use warnings;
use autodie;

my $fh;

open $fh, '<', 'file1.csv';
my $out = 'file2.csv';
open(FILE, '>', $out);

my $myline = "";
while (my $line = <$fh>) {
  chomp $line;
  unless ($line =~ m/^SID/) {
    $line =~ m/^(.*)$/;
    $myline = "\|$1";
  }
  print FILE $myline . "\n";
}

close $fh;
close FILE;

my file example:

SID,bla
foo bar  <- my code adds the pipe to the beginning of this line 

output should be like this:

SID,bla
| foo bar

but in my case I only print $myline, I know:

| foo bar
Was it helpful?

Solution

The line

$line =~ m/^(.*)$/

is misguided: all it does is put the contents of $line into $1, so the following statement

$myline = "\|$1"

may as well be

$myline = "|$line"

(The pipe | doesn't need escaping unless it is part of a regular expression.)

Since you are printing $myline at the end of your loop you are never seeing the contents of unmodified lines.

You can fix that by printing $line or $myline according to which one contains the required output, like this

while (my $line = <$fh>) {
  chomp $line;
  if ($line =~ m/^SID/) {
    print "$line\n";
  }
  else {
    my $myline = "|$line";
    print "$myline\n";
  }
}

or, much more simply, by dropping the intermediate variable and using the default $_ for the input lines, like this

while (<$fh>) {
  print '|' unless /^SID/;
  print;
}

Note that I have also removed the chomp as it just means you have to put the newline back on the end of the string when you print it.

OTHER TIPS

Instead of creating a new variable $myline, use the one you already have:

while (my $line =<$fh>) {
    $line = '|' . $line if $line !~ /^SID/;
    print FILE $line;
}

Also, you can use lexical filehandle for the output file as well. Moreover, you should check the return value of open:

open my $OUT, '>', $out or die $!;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top