0

I am writing a perl program which creates a procmailrc text file.

The output procmail requires looks like this: (partial IP addresses separated by "|")

\(\[54\.245\.|\(\[54\.252\.|\(\[60\.177\.|

Here is my perl script:

open (DEAD, "$dead");
@dead = <DEAD>;
foreach $line (@dead) { chomp $line; $line =~s /\./\\./g;
print FILE "\\(\\[$line\|\n"; }
close (DEAD);

Here is the output I am getting:

|(\[54\.245\.
|(\[54\.252\.
|(\[60\.177\.

Why is chomp not removing the line breaks? Stranger still, why is the '|' appearing at the front of each line, rather than at the end?

If I replace $line with a word, (print FILE "\(\[test\|"; }) The output looks the way I would expect it to look:

\(\[test|\(\[test|\(\[test|\(\[test|

What am I missing here?

So I found a work-around that does not use chomp: The answer was here:https://www.perlmonks.org/?node_id=504626

My new code:

open (DEAD, "$dead");
@dead = <DEAD>;
foreach $line (@junk) { 
$line =~ s/\r[\n]*//gm; $line =~ s/\./\\./g;  $line =~ s/\:/\\:/g;
print FILE "\\(\\[$line \|"; }
close (DEAD);

Thanks to those of you who gave me some hints.

ikegami
  • 367,544
  • 15
  • 269
  • 518
Konabob
  • 9
  • 4
  • I suspect there is a carriage return and line feed in your data which is causing the `|` character to show up at the start of line. Just a wild guess. try getting rid of all white space chars from `$line` – Red Cricket Jul 07 '18 at 17:07
  • The data is a list of IP addresses with carriage returns (\r). For each line of data, I am trying to chomp of that carriage return, then it should print the $line, and add the | character before the next $line is processed. I want the output to be all on one line. The s/// function seems to do what I expect it to do, but I am not comfortable with how I have chomp set up. There may be something else going on with my print command. I am baffled! – Konabob Jul 07 '18 at 19:03
  • chomp removes a trailing `\n`, not a `\r`... – Shawn Jul 07 '18 at 21:12
  • 2
    Post answers as answers, even if it's to your own question – ikegami Jul 07 '18 at 22:49
  • @Shawn [`chomp`](http://perldoc.perl.org/functions/chomp.html) removes whatever the current value of [`$/`](http://perldoc.perl.org/perlvar.html#$/) is, which is `\n` only by default. – haukex Jul 08 '18 at 09:08

1 Answers1

2

chomp removes the value of $/, which is set to the string produced by "\n" by default.

For input, however, you have

@dead = (
   "54.245\.\r\n",
   "54.252\.\r\n",
   "60.177\.\r\n",
);

This simple fix:

open(my $dead_fh, '<', $dead_qfn)
   or die("Can't open \"$dead_qfn: $!\n");

while (my $line = <$dead_fh>) {
   $line =~ s/\s+\z//;
   $line =~ s/\./\\./g
   print($out_fh "\\(\\[$line\|");
}

print($out_fh "\n");

(The alternative is to add the :crlf layer to your input handle.)

Using quotemeta makes more sense

open(my $dead_fh, '<', $dead_qfn)
   or die("Can't open \"$dead_qfn: $!\n");

while (my $line = <$dead_fh>) {
   $line =~ s/\s+\z//;
   print($out_fh quotemeta("([$line|"));
}

print($out_fh "\n");
ikegami
  • 367,544
  • 15
  • 269
  • 518