strspn
Returns the length of the leading run of characters that all belong to a given set.
strspn(string $string, string $characters, int $offset = 0, ?int $length = null): int- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$string | string | The string to examine. |
$characters | string | The list of allowable characters. |
$offsetoptional | int= 0 | The position in string to start searching. If negative, counts from the end of string. |
$lengthoptional | ?int= null | The length of the segment from string to examine. If negative, counts from the end of string. If null, examines to the end of string. |
Return value
intThe length of the initial segment of string which consists entirely of characters in characters.
Errors
Throws a ValueError if offset or length is not contained in string.
Changelog
- PHP 8.0.0length is nullable now.
strspn() walks a string from the start (or from offset) and counts how many consecutive bytes are members of the characters set. It stops at the first byte that is not in the set and returns the count. Its mirror image is strcspn(), which counts bytes that are not in the set.
When to reach for it
It is a hand-parser's tool. Splitting 120px into a number and a unit, measuring the indentation on a line, skipping leading whitespace, or checking that an identifier contains only allowed bytes are all one call. Because it returns a length, it pairs directly with substr().
A whole-string validity check is the idiom strspn($s, $allowed) === strlen($s), which is considerably faster than a regular expression for a fixed set of bytes.
What trips people up
The characters argument is a set of individual bytes, not a pattern and not a range. There is no a-z shorthand — you must spell out the alphabet, or use ctype_* or a regex instead.
The count is measured from offset, not from the start of the string, so strspn($s, $set, 3) returns a length relative to position 3.
Signs and decimal points are just characters. A digit set will report 0 for -5, because the minus is not in the set.
Example
When to use it
- Split a CSS-style value such as 120px into its numeric part and its unit.
- Measure the leading indentation of a line to reconstruct nesting.
- Verify that a username or token contains only characters from an allowed set.
Frequently asked questions
What is the difference between strspn and strcspn?
strspn counts leading characters that ARE in the given set; strcspn counts leading characters that are NOT in it. strcspn is the one to use to find the offset of the first delimiter.
Can I use a range like a-z with strspn?
No. The second argument is a literal list of individual bytes, so you must write out every character. Use ctype_alpha(), ctype_alnum() or a regular expression for ranges.
How do I check that a string contains only allowed characters?
Compare the span with the length: strspn($s, $allowed) === strlen($s). It is true only when every byte in the string belongs to the allowed set.
More examples
Splitting a number from its unit
120px splits into 120 and px, and 15% into 15 and %. auto has no leading digit so the number is reported as none. -5em also reports none, because the minus sign is not in the digit set — add '-' to the set, or handle the sign separately, if negative values are valid.
<?php
$inputs = ['120px', '15%', 'auto', '-5em'];
foreach ($inputs as $in) {
$n = strspn($in, '0123456789');
printf("%-6s number: %-6s unit: %s\n",
$in,
$n > 0 ? substr($in, 0, $n) : '(none)',
substr($in, $n));
}Validating an allowed character set
For the valid token the span equals the string length, so every byte was allowed. For 'abc-123' the span stops at 3, which is both the count of good bytes and the index of the first bad one — the hyphen — so the same number pinpoints the error position.
<?php
$allowed = 'abcdefghijklmnopqrstuvwxyz'
. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$token = 'abc123XYZ';
var_dump(strspn($token, $allowed) === strlen($token)); // bool(true)
$bad = 'abc-123';
$at = strspn($bad, $allowed);
echo "first illegal character at $at: ", $bad[$at], PHP_EOL;
Discussion