Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rewind next-search start position by 1?

How can I rewind the start of the next search position by 1? For example, suppose I want to match all digits between #. The following will give me only odd numbers.

my $data="#1#2#3#4#";

while ( $data =~ /#(\d)#/g ) {
  print $1, "\n";
}

But if I could rewind the start of the next position by 1, I would get both even and odd numbers.

This doesn't work: pos() = pos() - 1;

I know I can accomplish this using split. But this doesn't answer my question.

for (split /#/, $data) {
  print $_, "\n";
}
like image 558
n.r. Avatar asked Jul 21 '15 15:07

n.r.


2 Answers

One approach is to use a look-ahead assertion:

while ( $data =~ /#(\d)(?=#)/g ) {
  print $1, "\n";
}

The characters in the look-ahead assertion are not part of the matched expression and do not update pos() past the \d part of the regular expression.

More demos:

say "#1#2#3#4#" =~ /#(\d)/g;          #  1234
say "#1#2#3#4"  =~ /#(\d)/g;          #  1234
say "#1#2#3#4#" =~ /#(\d)(?=#)/g;     #  1234
say "#1#2#3#4"  =~ /#(\d)(?=#)/g;     #  123
like image 115
mob Avatar answered Oct 22 '22 20:10

mob


You're calling pos() on $_, instead of $data

From perldoc

Returns the offset of where the last m//g search left off for the variable in question ($_ is used when the variable is not specified)

So,

pos($data) = pos($data) - 1;
like image 8
mpapec Avatar answered Oct 22 '22 19:10

mpapec