Re: Substitute _last_ occurence in string?
by voyager (Friar) on Jul 25, 2001 at 18:30 UTC
|
$string = "one two three two four";
$gnirts = reverse $string;
$gnirts =~ s/ owt//;
$string = reverse $gnirts;
Reverse the string, remove the reverse of the desired token, then reverse the result.
Update: Full disclosure -- this was motivated by a node on sexeger I saw before. Props to japhy.
Update2: Fixed typo -- thanks Hofmator. | [reply] [d/l] |
Re: Substitute _last_ occurence in string?
by Hofmator (Curate) on Jul 25, 2001 at 18:38 UTC
|
my $string = 'one two three two four';
my $search = 'two ';
substr($string, rindex($string,$search), length $search, '');
print $string;
-- Hofmator
| [reply] [d/l] |
Re: Substitute _last_ occurence in string?
by japhy (Canon) on Jul 25, 2001 at 19:18 UTC
|
I'm glad people took the sexeger approach, for which this is an excellent example. Other approaches, like:
- s/two(?!.*two)//, and
- s/two(?!.*?two)//, and
- s/.*two//
suffer from things like slowness and too much backtracking.
_____________________________________________________
Jeff japhy Pinyan:
Perl,
regex,
and perl
hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??; | [reply] |
Re: Substitute _last_ occurence in string?
by MZSanford (Curate) on Jul 25, 2001 at 18:31 UTC
|
$string = reverse($string);
$string =~ s/owt //;
$string = reverse($string);
Thus spake the Master Programmer:
"When you have learned to snatch the error code from the trap frame, it will be time for you to leave."
-- The Tao of Programming | [reply] [d/l] |
Re: Substitute _last_ occurence in string?
by PrakashK (Pilgrim) on Jul 25, 2001 at 18:40 UTC
|
s/(two )(?!.*two )//
Probably valid only perl 5.6.0 +.
Update: Above works only if two is followed
by a space. It fails if:
$string = "one two three two four two";
The following works. Also, the parentheses around the first two are unnecessary.
$string =~ s/two\s*(?!.*two)//
| [reply] [d/l] [select] |
Re: Substitute _last_ occurence in string?
by Wookie (Beadle) on Jul 25, 2001 at 18:46 UTC
|
You can try to use the fact that '*' is greedy: $string=~s/(.*) two(.*)/$1$2/g;
When the first '.*' matches - it should go to the end of the line - and then work right to left to match the next part of the regex.
So in this case - it should find the last one.
game(Wookie,opponent) eq 'Wookie' ? undef $problem : remove_limbs(arms,opponent); | [reply] [d/l] |
|
| [reply] [d/l] |
|
This assumes that there is more than one 'two'. If there's only one instance, then the first instance is the last instance. I'd change this to:
$string =~ s/(.*)\s*two/$1/;
That way, you'll catch it if it's the first characters in the string.
Update: Ok. Given the suggestions, How about:
$string =~ s/(.*)(^|\s+)two/$1/;
| [reply] [d/l] [select] |
|
|
Re: Substitute _last_ occurence in string?
by scain (Curate) on Jul 25, 2001 at 18:37 UTC
|
Hello,
$string =~ s/two (.*?)$/$1/ should work, though after a little
testing, I find that it does not. I don't know why. Anyone?
Scott
Update: I must admit, I like the trickyness of using the reverse. | [reply] [d/l] |
|
Regexes always give you the leftmost longest match. To do something like you want you best use the greediness of .*
$string =~ s/(.*) two/$1/;
Update: I have simplified the unnecessarily complicated regex.
-- Hofmator
| [reply] [d/l] |