• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 297
  • Last Modified:

Perl subsituion

So i'm trying to get my head around the =~ s///;

in the following test  
@ =a
0=o
1=i

my $test = "M\@r10n";  ## this should by Marion
$test =~ s/\@/a/g; 
$test =~ s/0/o/g; # ok so far 
print  $test  outputs  Mar1on
# now test if 1 as a letter before or after it 
$test =~ s/\w(1)|(1)\w/i/g; # not good
print  $test  outputs  Maion

Open in new window


why is this picking up r1 and not just the 1 as i thought (1) puts the 1 into $1 and this is what is substituted?

Thanx
0
trevor1940
Asked:
trevor1940
  • 6
  • 2
  • 2
5 Solutions
 
lwadwellCommented:
Correct the (1) picks up the 1 and puts it into $1 .. which allow it to be used in the substitution ... but the entire match string gets substituted.  Think about this one ...
    $test =~ s/(\w)1/$1i/g;
0
 
ozoCommented:
$test =~ s/\w(1)|(1)\w/i/g; # not good
print  $test  outputs  Maion
What did you want as output?

 i thought (1) puts the 1 into $1
That's correct, but then you do not do anything with $1


Did you perhaps want
$test =~ s/\w(?=1)|(?<=1)\w/i/g;
which produces
Mai1in
or
$test =~ s/(?<=\w)1|1(?=\w)/i/g;
which produces
Marion
0
 
ozoCommented:
in the following test  
@ =a
0=o
1=i
Or did you want
$test = 'M@r10n';
$test =~ tr/@01/aoi/;
print $test;
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
trevor1940Author Commented:
ozo

$test =~ s/(?<=\w)1|1(?=\w)/i/g; worked

but what is (?<=\w) doing?

dose $test =~ tr/@01/aoi/;  have to be in that order
eg

 @ 0 1 = a o i
will

0 1 @ still = a o i or will become 0 i a
(spaces just for clarity)


lwadwell

I get what you doing your putting (\w) into $1

so how do you combine
  $test =~ s/(\w)1/$1i/g;
  $test =~ s/1(\w)/i$1/g;

into one line?
0
 
ozoCommented:
so how do you combine
  $test =~ s/(\w)1/$1i/g;
  $test =~ s/1(\w)/i$1/g;

into one line?

 $test =~ s/(\w)1|1(\w)/$1i$2/g;
#or
 s/(\w)1/$1i/g, s/1(\w)/i$1/g for $test;
0
 
ozoCommented:
$test =~ tr/@ 0 1/a o i/;  
can be
$test =~ tr/0 1 @/o i a/;  # (spaces need to be in the same place on both sides)
0
 
ozoCommented:
perl -MYAPE::Regex::Explain -e "print YAPE::Regex::Explain->new(qr/(?<=\w)1|1(?=\w)/i)->explain"
The regular expression:

(?i-msx:(?<=\w)1|1(?=\w))

matches as follows:
 
NODE                     EXPLANATION
----------------------------------------------------------------------
(?i-msx:                 group, but do not capture (case-insensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  (?<=                     look behind to see if there is:
----------------------------------------------------------------------
    \w                       word characters (a-z, A-Z, 0-9, _)
----------------------------------------------------------------------
  )                        end of look-behind
----------------------------------------------------------------------
  1                        '1'
----------------------------------------------------------------------
 |                        OR
----------------------------------------------------------------------
  1                        '1'
----------------------------------------------------------------------
  (?=                      look ahead to see if there is:
----------------------------------------------------------------------
    \w                       word characters (a-z, A-Z, 0-9, _)
----------------------------------------------------------------------
  )                        end of look-ahead
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------
0
 
ozoCommented:
$test =~ s/(\w)1|1(\w)/$1i$2/g;
and
 s/(\w)1/$1i/g, s/1(\w)/i$1/g for $test;
will have different results in the case of
$test='M@r1110n'
0
 
lwadwellCommented:
>> so how do you combine
>>  $test =~ s/(\w)1/$1i/g;
>>  $test =~ s/1(\w)/i$1/g;
>>into one line?

I wouldn't ... I was highlighting how the (selection) and $1 are used.  I would go with ozo's solution and use the modifier's to make the (select) non selective "s/(?<=\w)1|1(?=\w)/i/g;".
0
 
trevor1940Author Commented:
Thanx
Hope sharing points OK
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now