Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
I am attempting to remove 3 commas from the file below but it is not working.
#!/usr/bin/perl
use strict;
use warnings;
my @data;
my @line;
open(FH, "error_log");
@data = <FH>;
foreach $line (@data) {
if ($line =~ /notice/) {
if ($line =~ /rdy/) {
$line =~ s/ /,/g;
my @L1 = split(/notice|[[]|mpmstats:[\t]/, $line);
foreach $line (@L1) {
$line =~ s/,,,/,/g;
print @L1;
}
}
}
}
My output is as follows.
Wed,Jun,13,10:23:35,2012,,,rdy,769,busy,31,rd,0,wr,22,ka,6
Why is the s/,,,/,/g; not substituting the single comma?
Re: Perl substitution not working
by syphilis (Archbishop) on Jun 21, 2012 at 00:48 UTC
|
Why is the s/,,,/,/g; not substituting the single comma?
I think one possibility is that the three commas are spread over two adjoining elements of @L1. If the 3 commas don't belong to the same $line, the regex won't remove them. Try print "@L1"; so you can see whether the 3 commas belong to the same $line.
Cheers, Rob
| [reply] [d/l] |
Re: Perl substitution not working
by 2teez (Vicar) on Jun 21, 2012 at 00:40 UTC
|
How does your input look like? Why slurp your whole file into an array, only to iterate later, in order to inter- change or ( do substitution ) on the array indexes. Am sure there are better ways of achieving your aim using a while loop with the open function. You can try y/,,,/,/s like so:
my $value='Wed,Jun,13,10:23:35,2012,,,rdy,769,busy,31,rd,0,wr,22,ka,
+6 ';
$value=~y/,,,/,/s;
print $value; ## Wed,Jun,13,10:23:35,2012,rdy,769,busy,31,rd,0,wr,
+22,ka,6
If I may suggest the following, use open function three argument, check if the open function fails and always close open file handler as soon as possible like so:
open my $filehandler,'<',$file or die "can't open file: $!";
# .... others codes
close $filehandler or die "can't close file:$!";
| [reply] [d/l] [select] |
Re: Perl substitution not working
by Lotus1 (Vicar) on Jun 21, 2012 at 00:50 UTC
|
Global symbol "$line" requires explicit package name at 977513.pl line
+ 11.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 12.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 13.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 14.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 15.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 16.
Global symbol "$line" requires explicit package name at 977513.pl line
+ 17.
Execution of 977513.pl aborted due to compilation errors.
| [reply] [d/l] |
Re: Perl substitution not working
by muba (Priest) on Jun 21, 2012 at 00:45 UTC
|
My guess? Because the commas are each part of another element of @L1, because they had "notice", "[", "mpmstats:", or "\t" inbetween them.
Try this fix:
# ...
if ( ($line =~ /notice/) && ($line =~ /rdy/) )
# Spaces to commas
$line =~ s/ /,/g;
# Get rid of "notice", "[", "mpmstats:", and tabs inside the line.
$line =~ s/notice|\[|mpmstats:|\t//g;
# Change the dreaded Triple Comma into the nice and smooth Single
+Comma.
$line =~ s/,,,/,/g;
# Or even the following if you want to replace all multiple subs
+equent commas by
# just one:
# $line =~ s/,,+/,/g;
# Show me what I've got
print $line;
}
See how I wrote your [[] as \[? I think it's more readable that way. Also, regular expression understand \t just fine. There's no need to put it into a character class. And if ( ($line =~ /notice/) && ($line =~ /rdy/) ) { pretty much does the same thing as your two if statements. The inner parens are optional, but I prefer to write it that way. | [reply] [d/l] [select] |
Re: Perl substitution not working
by frozenwithjoy (Priest) on Jun 21, 2012 at 00:44 UTC
|
Well, the good news is that s/,,,/,/g should definitely work. The bad news is that your script is doing something weird. :P A couple things to be aware of:
-
you don't need to make @line an array. You can just write something like foreach my $line (@data).
-
you are using $line for both foreach loops. You are trying to use the same namespace for two different things. Maybe change the second one to foreach my $L1_line split...
-
Disregard this: The actual reason you aren't substituting properly is that you are printing @L1, but that array never gets modified by your substitution which acts on $line.
| [reply] [d/l] [select] |
|
my @L1 = qw(Abc aBc abC);
for my $line (@L1) {
$line =~ s/a/_/i;
print "\@L1: <", join(", ", @L1), ">; \$line: <$line>\n";
}
__END__
@L1: <_bc, aBc, abC>; $line: <_bc>
@L1: <_bc, _Bc, abC>; $line: <_Bc>
@L1: <_bc, _Bc, _bC>; $line: <_bC>
| [reply] [d/l] |
|
|