Vivek Sharma
Vivek Sharma

Reputation: 103

modifying attribute in $self using regex

I am new to perl and i am having issues in modifying an attribute under saved in $self.

I have an attribute called "devices" inside $self, if I print it in perl debugger it prints like this :

DB<22> x $self->{devices}
0  ARRAY(0xa1ec308)
0  "BG-SOKU-SAA01\cM\cJBG-SOKU-TS01 BG-SOKU-DCN01"

Now I want to replace \cM\cJ and whitespace with commas in the above attribute. So I am writing a regex for it which is like this :

my @dM= @{$self->{devices}};
$dM[0]=~ s/\cM\cJ/,/g;
$dM[0]=~ s/ /,/g;

Now when I print the $self->{devices} it gives me this :

DB<22> x $self->{devices}
0  ARRAY(0xa1ec308)
0  'BG-SOKU-SAA01,BG-SOKU-TS01,BG-SOKU-DCN01'

RegEx works but when I pass it to some other class and try to iterate over it, it takes comma separated device names as one single value rather than taking 1 device name each.

I dont know what is going wrong.

Please help me out with this.

Upvotes: 1

Views: 87

Answers (1)

Sobrique
Sobrique

Reputation: 53488

I think your problem will be that $self -> {devices} is actually a single element array - containing the string 'BG-SOKU-SAA01,BG-SOKU-TS01,BG-SOKU-DCN01'

The implication is you want this to be an array - this is relatively easily achieved via split

@{$self -> {devices}} = map { split /,/ } @{$self -> {devices}} 

Given you're already transforming on delimiters first though - you can probably do the same on that.

@{$self -> {devices}} = map { split /(?:\\cM\\cJ|\s+)/ } @{$self -> {devices}}

map is one of those "dark magic" perl functions - what it does is list transformation.

  • We take the source list - in this case @{$self -> {devices}}
  • iterate through it applying a code block. split /,/ - this returns zero or more elements (we split each element on commas), which is added to the new list.
  • and then we assign the new list.

This is basically the same as:

my @new_list;

foreach my $element ( @{$self -> {devices}} ) {
    my @tmp = split /,/, $element;
    push ( @new_list, @tmp ); 
}

$self -> {devices} = \@new_list; 

The second example is essentially the same, but using the fact that split can take a regular expression.

By using: (?:\\cM\\cJ|\s+)

So we call either: \cM\cJ a delimiter or \s+ which is regular expression for "one or more whitespace". Which is why it handles tabs, linefeeds, multiple spaces etc.

Note - the (?: at the start is important, because it denotes a non capturing group. If you use a capture (() usually) then that will be 'returned' as part of the map operation, so you'll end up with an unwanted element \cM\cJ because the regular expression captured it.

Try getting to grips with Data::Dumper.

use Data::Dumper;

then

print Dumper $self;

This will help you understand the contents of your object.

Upvotes: 2

Related Questions