4

Hi im trying to find all overlapping substrings in a string here is my code its only finding nonrepeating ACA.

$haystack = "ACAAGACACATGCCACATTGTCC";
$needle = "ACA";
echo preg_match_all("/$needle/", $haystack, $matches);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
lolsharp
  • 69
  • 1
  • 11

2 Answers2

3

You're using echo to print the return value of preg_match_all. That is, you're displaying only the number of matches found. What you probably wanted to do was something like print_r($matches);, like this:

$haystack = "ACAAGACACATGCCACATTGTCC";
$needle = "ACA";
preg_match_all("/$needle/", $haystack, $matches);
print_r($matches);

Output:

Array
(
    [0] => Array
        (
            [0] => ACA
            [1] => ACA
            [2] => ACA
        )

)

Demo

If your real concern is that it counted ACACA only once, well, there are three things that need to be said about that:

  1. That's basically unavoidable with regex.
  2. You really shouldn't count this twice, as it's overlapping. It's not a true recurrence of the pattern.
  3. That said, if you want to count that twice, you could do so with something like this:

    echo preg_match_all("/(?=$needle)/", $haystack, $matches);
    

    Output:

    4
    

    Demo

elixenide
  • 44,308
  • 16
  • 74
  • 100
  • but I need the overlapping ACA too thats my issue – lolsharp Mar 15 '17 at 02:29
  • //TT occurs twice in TTT! – lolsharp Mar 15 '17 at 02:31
  • @lolsharp The `(?=...)` is what's called a "positive look-ahead assertion." It means, "See if what's next is *xyz*, but don't move the cursor." It allows us to find each spot where you have `ACA` (or whatever `$needle` is), without "consuming" those three characters. The next match can be only one character further along. – elixenide Mar 15 '17 at 02:39
0

Here a script to find all occurences of a substring, also the overlapping ones.

    $haystack = "ACAAGACACATGCCACATTGTCC";
    $needle   = "ACA";

    $positions    = [];
    $needle_len   = strlen($needle);
    $haystack_len = strlen($haystack);

    for ($i = 0; $i <= $haystack_len; $i++) {
        if( substr(substr($haystack,$i),0,$needle_len) == $needle){
            $positions[]=$i;
        }
    }
    print_r($positions);

Output: Array ( 0, 5, 7, 14 )

TortelliEngineer
  • 183
  • 1
  • 2
  • 13