Probably a dereferencing problem - maybe???

M

Mike Flannigan

I have some code below that works fine. It finds duplicates on
one field and marks them as duplicates. But I'd like to also
remove all quotes (") from the file also. The 3 commented out
lines are some of my attempts at doing this. They all give errors
like:
"Applying substitution (s///) to @array will act on scalar
(@array) at . . . line 31. Can't modify private array in
substitution (s///0 at . . . line 31 near "s/"//s;"

I can get this done outside this script, but was wondering if
there is an easy way to do this inside this script.


Mike Flannigan

________________________________

use strict;
use warnings;

my $old_file = 'bb1.txt';
my $new_file = 'bb2.txt';

open WPIN, $old_file or die "Cannot open $old_file: $!";
my @data = map [ split /\t/, $_, 6 ], <WPIN>;
close WPIN;

#@data =~ s/"//gs;

open WPOUT, ">", $new_file or die "$0: open $new_file: $!";

my %saw;
for my $line (@data) {
# $line =~ tr/"//d;
if ($saw{ $line->[ 4 ] }++) {
print "found dup\n";
$line->[ 0 ] .= "+++++";
}
# @$line =~ tr/"//d;
print WPOUT join("\t" => @$line);
}

close WPOUT or warn "$0: close $new_file: $!";


__END__


DATA

Canoe Valley Grapevine Hills Brewster valley 292756N1030910W "TX, Texas"

Cantrell Mountain Hacienda Uvalde summit 291204N0995833W "TX, Texas"
Casa Grande Peak The Basin Brewster summit 291603N1031711W "TX, Texas"
Cassiano Park San Antonio West Bexar park 292449N0983144W "TX, Texas"
Cedar Grove Cemetery Sanderson Terrell cemetery 300754N1022309W "TX,
Texas"
Centeno Park San Antonio West Bexar park 292513N0983232W "TX, Texas"
 
T

Tad McClellan

Mike Flannigan said:
I'd like to also
remove all quotes (") from the file also.
^^^^^^^^^^^^^

It looks to me like you want to remove all quotes (") from an *array*.

#@data =~ s/"//gs;


The s///s is a no-op, so it should not be there.

"s" only affects dot, it is a mistake to apply it when there
are no dots in the pattern.


s/"//g foreach @data;

or, better yet, use the Right Tool for jobs involving characters
(rather than patterns):

tr/"//d foreach @data;
or
tr/"//d for @data;

or, if you don't like that "reversed" form:

foreach ( @data ) {
tr/"//d
}


See the "Foreach Loops" section in perlsyn.pod to learn about
the "alias"ing that foreach() does for you.

# $line =~ tr/"//d;


That looks familiar. :)
 
M

Mike Flannigan

Tad said:
It looks to me like you want to remove all quotes (") from an *array*.

Right you are.

The s///s is a no-op, so it should not be there.

"s" only affects dot, it is a mistake to apply it when there
are no dots in the pattern.

I don't follow you entirely there, but that's OK. I know what
you are saying ( . as in match any character), but don't know
what that has to do with /s. I think I am totally confused about
the difference between /s and /m. I'll figure it out someday.

s/"//g foreach @data;

Thank you. I was just signing on again to say I found the
answer myself, though not as good an answer as yours
above. I tried

$line->[ 0 ] =~ tr/"//d;
$line->[ 5 ] =~ tr/"//d;

and it worked.
 
T

Tad McClellan

Mike Flannigan said:
Tad McClellan wrote:
I don't follow you entirely there, but that's OK. I know what
you are saying ( . as in match any character), but don't know
what that has to do with /s.


dot does NOT match any character.

dot matches any character except a newline.

the "s" option makes dot match any character.

it is senseless to change the meaning of dot when there is no dot.

I think I am totally confused about
the difference between /s and /m. I'll figure it out someday.


Why not today?

/s makes dot match a newline character.

/m makes ^ and $ match beginning/end of a _line_ rather than
beginning/end of the string. ie. It matches "interior" lines begins/ends.

If there is no dot in your pattern, then you do not _need_ to
understand /s, because you should not be using it.

If there is no anchor ( ^ or $ ) in your pattern, then you do not _need_ to
understand /m, because you should not be using it.
 
M

Matija Papec

X-Ftn-To: Mike Flannigan

Mike Flannigan said:
I don't follow you entirely there, but that's OK. I know what
you are saying ( . as in match any character), but don't know
what that has to do with /s. I think I am totally confused about
the difference between /s and /m. I'll figure it out someday.

You want to use /s in case you want to . match the newline, and /m
only to say anchors(^ and $) to match begining/end of line.

perldoc perlretut

* no modifiers (//): Default behavior. '.' matches any character
except "\n". "^" matches only at the beginning of the string and "$"
matches only at the end or before a newline at the end.

* s modifier (//s): Treat string as a single long line. '.' matches
any character, even "\n". "^" matches only at the beginning of the
string and "$" matches only at the end or before a newline at the
end.

* m modifier (//m): Treat string as a set of multiple lines. '.'
matches any character except "\n". "^" and "$" are able to match at
the start or end of *any* line within the string.

* both s and m modifiers (//sm): Treat string as a single long line,
but detect multiple lines. '.' matches any character, even "\n". "^"
and "$", however, are able to match at the start or end of *any*
line within the string.
 
B

Bob Walton

Mike said:
I have some code below that works fine. It finds duplicates on
one field and marks them as duplicates. But I'd like to also
remove all quotes (") from the file also. The 3 commented out
lines are some of my attempts at doing this. They all give errors
like:
"Applying substitution (s///) to @array will act on scalar
(@array) at . . . line 31. Can't modify private array in
substitution (s///0 at . . . line 31 near "s/"//s;"


See comments below.

I can get this done outside this script, but was wondering if
there is an easy way to do this inside this script.


Mike Flannigan

________________________________

use strict;
use warnings;

my $old_file = 'bb1.txt';
my $new_file = 'bb2.txt';

open WPIN, $old_file or die "Cannot open $old_file: $!";
my @data = map [ split /\t/, $_, 6 ], <WPIN>;


This returns a six-element array, the value of which is a reference to
an anonymous array with one entry for each line's data. I think perhaps
the \t character you were attempting to split on got lost in the email
translation -- where were the tabs supposed to be? I punted and guessed
there were supposed to be five tabs.

close WPIN;

#@data =~ s/"//gs;


This one won't work because you are attempting to use array @data where
a scalar is expected. Hence, @data will evaluate to the number of
elements in @data, which is a non-lvalue. Also, no need for the /s
modifier in this case. I'm guessing you probably want something like:

$$_[5]=~s/"//g for @data;

open WPOUT, ">", $new_file or die "$0: open $new_file: $!";

my %saw;
for my $line (@data) {
# $line =~ tr/"//d;


This one won't work because $line is an array reference. Maybe
something like:

$line[5]=~tr/"//d;

would have worked?

if ($saw{ $line->[ 4 ] }++) {
print "found dup\n";
$line->[ 0 ] .= "+++++";
}
# @$line =~ tr/"//d;


Again, @$line is an array, and, when used where a scalar is expected,
the scalar result is the number of elements in the array, and is not an
lvalue.

print WPOUT join("\t" => @$line);
}

close WPOUT or warn "$0: close $new_file: $!";


__END__


DATA

Canoe Valley Grapevine Hills Brewster valley 292756N1030910W "TX, Texas"

Cantrell Mountain Hacienda Uvalde summit 291204N0995833W "TX, Texas"
Casa Grande Peak The Basin Brewster summit 291603N1031711W "TX, Texas"
Cassiano Park San Antonio West Bexar park 292449N0983144W "TX, Texas"
Cedar Grove Cemetery Sanderson Terrell cemetery 300754N1022309W "TX,
Texas"
Centeno Park San Antonio West Bexar park 292513N0983232W "TX, Texas"

HTH.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top