Strings7 min readExamples run on PHP 8.5.10

sscanf()

Learn how PHP 8.4 sscanf() parses values out of a string using a printf-style format, with return values, edge cases and common mistakes.

Signature

sscanf(string $string, string $format, mixed &...$vars): array|int|null
Available since PHP 4.0.17.48.08.18.28.38.48.5All versions →

Purpose

sscanf() is the input counterpart of printf(). Instead of building a string from values, you give it an existing string and a format, and it extracts the values that the format describes. It suits short, regular text such as codes (SN/2350001), dates (2024-03-15) or simple records where a full regular expression feels heavy.

The format is based on the one used by sprintf(), with a few differences that matter when reading input. Conversions are typed: %d produces an integer, %s a string, and so on.

Signature

Parameters

  • $string: the input text to parse.
  • $format: the pattern to match. Literal characters must match exactly. Any whitespace in the format matches any run of whitespace in the input, so a tab in the format can match a single space.
  • ...$vars: optional variables passed by reference. Each one receives the value of one conversion, in order. There is no default; if you leave them out, you get an array instead.

Some format details specific to sscanf():

  • %d reads a decimal number, and %i reads an integer with base detection.
  • %s stops at the first whitespace character, so it reads one word.
  • %n yields the number of characters processed so far.
  • * in place of an argument number (as in %*d) matches the value but discards it.
  • F, g, G and b are not supported, and the function is not locale-aware.

Return value and failure cases

The return type depends on how you call it:

  • With only two arguments, it returns an array of the parsed values. A conversion that could not be filled leaves null in its slot.
  • With extra variables, it returns the number of values assigned.
  • If the format expects more substrings than the input contains, null can be returned. With variables, reaching the end of the input before anything has been parsed returns -1.

Parsing stops at the first mismatch. Everything before it is kept, and the rest stays unassigned. The function does not throw for ordinary non-matching text, so check the result yourself.

Example 1: Reading an array of values

When you pass no variables, you receive a list. Here the literal labels in the format must match, and the whitespace between tokens is flexible.

Example
<?php
$result = sscanf("age: 25 name: Bob", "age: %d name: %s");
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
[25,"Bob"]

The integer comes back as a real int and the name as a string.

Example 2: Assigning into variables

Passing variables by reference makes the function return a count instead of an array. This is handy for confirming that every field was parsed.

Example
<?php
$count = sscanf("2024-03-15", "%d-%d-%d", $year, $month, $day);
echo json_encode([$count, $year, $month, $day]), "\n";
Output
[3,2024,3,15]

Note that 03 becomes the integer 3, because %d converts to a number and drops the leading zero.

Example 3: Skipping fields and partial matches

Use %*d to match a number without keeping it. When the input stops matching, the unfilled slots are null.

Example
<?php
$skipped = sscanf("10 20 30", "%d %*d %d");
$partial = sscanf("12 apples", "%d %d");
echo json_encode([$skipped, $partial]), "\n";
Output
[[10,30],[12,null]]

The first call returns only the first and third numbers. The second call parses 12, fails on apples, and leaves the second slot as null.

Edge cases

  • Whitespace is flexible. One space in the format matches several spaces or a tab in the input, but it never requires a specific kind.
  • %s reads one word. To capture text with spaces, use a character set such as %[^,] to read up to a delimiter, or split the string yourself.
  • Types follow the conversion. %d gives integers and %s gives strings. Validate ranges afterward, since the function only checks the shape of the text.
  • Partial results are normal. A failure in the middle does not discard earlier values, so a null entry is the signal that parsing stopped.
  • Base detection. %i accepts prefixes that %d does not, so use it only when you want that behavior.

Common mistakes

  1. Expecting %s to include spaces. "Lewis Carroll" with %s yields only Lewis. Use two %s conversions or a character set.
  2. Not checking for null. Always test the array for null entries, or compare the returned count with the number of conversions you expected.
  3. Mixing up the two return styles. With variables you get a count, not the values. Reading the return value as an array in that mode is a bug.
  4. Mismatched variable count. The number of variables should match the number of non-suppressed conversions. A mismatch is a usage error.
  5. Treating it as validation. sscanf("12abc", "%d") succeeds with 12. If the whole string must be numeric, use a stricter check.
  6. Assuming locale handling. Decimal separators are not locale-aware, so do not rely on locale settings to parse formatted numbers.
  • sprintf() and printf(): build formatted output with the same style of format.
  • fscanf(): the same parsing applied to lines read from a file.
  • vsprintf(), vprintf() and fprintf(): formatted output variants.
  • explode(), preg_match() and str_getcsv(): alternatives when the text is delimiter-based or irregular.

Recap

sscanf() parses a string against a printf-style format. Without variables it returns an array, with variables it returns the count of assigned values, and unmatched slots are null. Remember that %s stops at whitespace, %*d skips a value, and parsing halts at the first mismatch, so check the result before using it.

Tested examples

Reading an array of values
<?php
$result = sscanf("age: 25 name: Bob", "age: %d name: %s");
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n";
Output
[25,"Bob"]
Assigning into variables
<?php
$count = sscanf("2024-03-15", "%d-%d-%d", $year, $month, $day);
echo json_encode([$count, $year, $month, $day]), "\n";
Output
[3,2024,3,15]
Skipping fields and partial matches
<?php
$skipped = sscanf("10 20 30", "%d %*d %d");
$partial = sscanf("12 apples", "%d %d");
echo json_encode([$skipped, $partial]), "\n";
Output
[[10,30],[12,null]]