0

I want to find the place of a digit-based substring in a string as

$str = " test No. 82 and No. 8 more No. 234";
$needle = "No. 8";

I tried strpos as

$index = stripos($str,$needle);

but it finds No. 82 instead of No. 8.

Is the simplest way to use preg_match with PREG_OFFSET_CAPTURE? Does it really necessarily regex?

4
  • Why do you need the indices? A regex can do more than just return the indices. What is the final ideal result? Commented Oct 26, 2016 at 11:02
  • what does the place of digits mean? the left position(index) of each number OR should it be a range with (left boundary, right boundary) for each matched item? Commented Oct 26, 2016 at 11:02
  • @WiktorStribiżew I use it as an offset in another strpos to find a substring after the digits. Commented Oct 26, 2016 at 11:12
  • 1
    Is that an XY problem then? What is the real text you need to get from the above string? Commented Oct 26, 2016 at 11:13

2 Answers 2

3

"Regex" approach would be preferable for such complex cases, preg_match_all function will do the job:

$str = " test No. 82 and No. 8 more No. 234";
preg_match_all("/No\.\s+\d+\b/", $str, $matches, PREG_OFFSET_CAPTURE);

print_r($matches[0]);

According to your additional condition with search $needle:
- we should consider the right boundary of the search "needle" by using metacharacter \b

$str = " test No. 82 and No. 8 more No. 234";
$needle = "No. 8";
preg_match_all("/$needle\b/", $str, $matches, PREG_OFFSET_CAPTURE);

print_r($matches[0]);

The output:

Array
(
    [0] => Array
        (
            [0] => No. 8
            [1] => 17
        )
)
Sign up to request clarification or add additional context in comments.

Comments

1

You will need a regular expression to match the precise sequence pattern. I suggest this apporach:

<?php
$subject = " test No. 82 and No. 8 more No. 234";
$pattern = '/No\. \d+/';
$offset = 0;
while (preg_match($pattern, $subject, $matches, PREG_OFFSET_CAPTURE, $offset+1)) {
    $offset = $matches[0][1];
    var_dump($matches);
}

The output, which of course can be further processed, is:

array(1) {
  [0] =>
  array(2) {
    [0] =>
    string(6) "No. 82"
    [1] =>
    int(6)
  }
}
array(1) {
  [0] =>
  array(2) {
    [0] =>
    string(5) "No. 8"
    [1] =>
    int(17)
  }
}
array(1) {
  [0] =>
  array(2) {
    [0] =>
    string(7) "No. 234"
    [1] =>
    int(28)
  }
}

Depending on your exact requirements you may want to modify the pattern to '/No\. (\d+)/' to match exactly the numeric parts. You also will have to adapt the offset line to $offset = $matches[1][1]; then obviously.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.