A backwards implementation to get up to f(il, o, ro)
# (?s)(?:.(?<!file)(?<!for)(?<!from))+
edit
Using a lookbehind is forever pathological.
So to save face, below are 2 ways I know to do it in a fairly simple way.
The first is to use split, which is straight forward.
(?<=fil)(?=e)|(?<=fo)(?=r)|(?<=fro)(?=m)
The second way is fairly simple. Find up until beginning of file|for|from
then match any remaining fil|fo|fro
.
This will match every character, something a lookbehind won't do.
Example using both split and the straight regex are in the test case.
Regex explained
# (?s)(?:(?!file|for|from).())*(?:(?:fil|fo|fro)())?(?=\1|\2)
(?s) # Dot-All
(?: # Optional group, do many times
(?! file | for | from ) # Lookahead, not 'file', 'for', 'from'
. # Match this character
( ) # Set a Group 1 flag (empty, but defined)
)*
(?: # Optional group, do once
(?: fil | fo | fro ) # 'fil'(e), 'fo'(r), 'fro'(m)
( ) # Set a Group 2 flag (empty, but defined)
)?
(?= \1 | \2 ) # See if we matched at least 1 character
# (this could be done with a conditional,
# but not all engines have it)
Perl test case.
$/ = undef;
$str = <DATA>;
# Using Split()
my @ary = split(/(?<=fil)(?=e)|(?<=fo)(?=r)|(?<=fro)(?=m)/, $str);
for (my $i = 0; $i < @ary; $i++)
{
print $ary[$i],"\n";
}
print "----------\n";
# Using just Regex
while ($str =~ /(?s)(?:(?!file|for|from).())*(?:(?:fil|fo|fro)())?(?=\1|\2)/g )
{
print $&, "\n";
}
__DATA__
this file is a frozen filled football from Steve, for trackingfromforfile
Output >>
this fil
e is a frozen filled football fro
m Steve, fo
r trackingfro
mfo
rfil
e
----------
this fil
e is a frozen filled football fro
m Steve, fo
r trackingfro
mfo
rfil
e