You scan H12 and the field shows H1. The pattern is not the problem: ([HDP]\d+) — or the equivalent ([HDP]\d{1,}){1} — is valid, and any regex tester proves it. The problem is when the match is allowed to fire. A scanner input that applies the pattern to the arriving character stream returns on the first match it can complete, and two characters are enough to complete this one. The sections below cover the mechanism, the three checks in order of probability, the three fixes and the four-scan test that proves whichever fix you pick. They are for anyone parsing barcode data from a handheld scanner or a fixed code reader into software, a PLC or a database.
Why a correct pattern returns one character
A regular expression engine matches against the string it is given. A tester receives the complete scan H12, and the greedy digit quantifier consumes both digits. A live scanner input does not wait for a complete string: it re-evaluates the pattern against its buffer every time a character arrives and returns on the first match. After H there is no match, because the digit quantifier needs at least one digit. After H1 the pattern is satisfied, the input declares the read done, and the trailing 2 reaches a parser that has already moved on.
Greediness never gets the chance to help you here. The digit quantifier is greedy only within a single match attempt on a single string, and this engine never sees H12 as one string. The outer {1} and the {1,} spelling are not the cause either; the usual-advice section below takes them apart.
The table is the whole failure, character by character, for a scan of H12 followed by a carriage return:
| Character arriving | Buffer | ([HDP]\d+) |
([HDP]\d+)\r |
|---|---|---|---|
| H | H |
no match: needs a digit | no match |
| 1 | H1 |
match fires, returns H1 — too early | no match: no CR yet |
| 2 | H12 |
— already returned | no match |
| CR | H12\r |
— | match fires; group 1 holds H12
|
The fix follows from the last column: make the pattern unsatisfiable until the read is genuinely over. Every scanner interface has such a point — the terminator character the scanner emits after the data — and getting that byte into the pattern removes the early fire.
Check in this order
Work down the list; the first cause explains most cases.
-
The pattern can match a partial read. The test takes one minute: type the code into the input's test or monitor window one character at a time. If the parsed value appears after the first digit, the pattern fires early, and Fix 1 ends it.
-
The scanner sends no terminator. Log the raw stream and read the final byte; the capture-without-a-prefix guide shows how to watch bytes as they arrive. Nothing after the last digit — or a printable character you did not intend — leaves Fix 1 with nothing to anchor to. Set a suffix in the scanner's data-output settings first: a carriage return is the usual keyboard-wedge default, and a printable character such as # works just as well.
-
The tool frames on prefix and suffix and never runs the regex. Set a suffix, scan, and log what the parser receives. Some inputs treat the framing pair as the message boundary and apply no pattern at all; in that case the framing is the fix and the regex field is unused configuration. Fix 3 shows how to tell the two behaviors apart.
Fix 1: put the terminator in the pattern
Append the terminator outside the capture group:
The engine cannot declare a match until that final character arrives, and it arrives exactly once per scan, after the last digit. Capture group 1 then holds the complete code: H12, D5, P12. Grouping constructs do this job: the parentheses delineate the subexpression you want captured, and everything outside them — the terminator included — is matched but not captured. A non-capturing group (?:...) does the same when you need grouping without capturing.
Match what the scanner actually sends. Enter is CR (ASCII 13); some readers send CR followed by LF (ASCII 10), which needs \r\n at the end of the pattern. Keep the terminator outside the parentheses so group 1 stays the clean code. If the tool outputs the whole match rather than a group, map group 1 in the output settings, or assert the terminator with a lookahead, (?=\r), which the engine checks without consuming. The regex parsing guide covers capture groups and output mapping in depth.
Fix 2: anchor the pattern for whole-line inputs
If the input delivers complete messages — a serial read that returns one scan per read, or a text field that receives Enter as an end-of-line — anchor both ends with ^([HDP]\d+)$.
The start anchor rejects a stray fragment before the code; the end anchor refuses a match until the buffer ends. Most engines let $ sit just before a trailing newline; when even that must fail the match, use the strict end-of-string anchor your engine offers, commonly \z (the .NET spelling is \Z for end of input or before a final \n, and \z for strict end). Check your engine's anchor table before relying on the distinction.
On line-delivered input the anchors add a guarantee Fix 1 does not: a fragment of the previous scan stuck to the front of the code prevents the match instead of corrupting it, so a bad read is visible rather than wrong.
Fix 3: frame the data with prefix and suffix
Configure the data output with a prefix and suffix — @ before the code and # after it is a common pairing — and let the framing delimit each read. Two behaviors exist in input tools: frame first, then run your pattern on the inner data; or treat the framing as the message boundary and skip the pattern field entirely. One scan and a log tell you which you have. If the value arrives complete with the pattern field empty, the framing is the anchor and you are done. If the pattern still runs, it now sees only the inner string, and the suffix guarantees it cannot fire early.
Framing also cleans up the neighboring failures: variable-length codes arriving glued together, or a field split by a stray character. The prefix and suffix framing guide plans the framing pair itself, and the variable-length input guide covers codes whose length changes from scan to scan.
Decision: a raw character stream takes Fix 1 with the byte your log shows; whole messages per read take Fix 2; a tool with framing takes Fix 3, and if the pattern still runs, add the suffix character to the pattern as well.
Prove it with a four-scan test
Scan or inject the shortest and longest codes you issue and check the parsed value and its length:
| Scan | Bytes sent | Correct parse |
|---|---|---|
| H1 | H, 1, CR | H1 — 2 characters |
| H12 | H, 1, 2, CR | H12 — 3 characters |
| D5 | D, 5, CR | D5 — 2 characters |
| P12 | P, 1, 2, CR | P12 — 3 characters |
All four rows must be exact. A pass on H12 with a fail on H1 means the pattern turned too strict, usually a quantifier minimum; a pass on H1 with a fail on H12 means the early fire is back. Keep the raw-byte log from the diagnosis: the byte at the end of every scan is the character that belongs in the pattern. One leftover trap: a scanner that sends CR followed by LF with a pattern ending in \r fires correctly but leaves the LF in the buffer, where it can glue itself to the next scan — write \r\n or clear the buffer after each match.
When the usual advice fails
A regex tester is the wrong oracle for this failure. It answers one question, whether the pattern describes the string; a streaming input answers another, when the match may fire. A pattern that passes the tester and truncates on the line is not a contradiction — it is two different tests.
Quantifier edits fail for the same reason. ([HDP]\d{2,}) blocks the early fire on H1, but rejects H1, D1, D5 and P1 outright — four of the six valid codes — and still fires after two digits whenever a third is on the way. A pattern cannot see the future; only a terminator or a message boundary tells it the read is complete.
The original pattern was never miswritten either. {1,} is the long spelling of +, and a group repeated exactly once is the group itself, so ([HDP]\d{1,}){1}, ([HDP]\d+) and the anchored form all describe the same strings. Rewrite the firing condition, not the character classes.
Readers and interfaces: where the terminator comes from
Every input path gives you a boundary somewhere, and the parsing rules are identical on all of them. A USB keyboard-wedge scanner ends each scan with Enter. A serial or TCP reader emits one message per read; the input methods guide maps the interfaces and the PLC communication guide plans the reader-to-PLC link end to end.
A fixed industrial code reader on a line pushes decoded strings over Ethernet or USB to the host; the same discipline applies, and the HMI serial port guide covers framing on the display side. Decide once where the terminator is born — the reader's output settings, the host tool's framing, or your own parser — and keep the pattern matched to it.
If you are specifying the reader hardware as well, the shop's fixed code readers span compact USB units to logistics models:
1D/2D codes on the line
658 models · from $399.00Three of them, one per interface family:
- Interface
- Fast Ethernet
- Resolution
- Up to 3 MP
- Interface
- GigE
- Resolution
- Up to 3 MP
- Resolution
- Up to 3 MP
- Shutter
- Global
The MV-ID3013PM-12M-WBN is a compact Fast Ethernet reader with a 12 mm focal length and 1.3 MP resolution. The MV-ID813M-05S-WBN-SR pairs white light illumination with a 4.9 mm focal length on GigE. The LS-CRD-0047 reads at a 60-120 mm reading distance over USB 2.0 with 1.2 MP resolution. Whichever you choose, the parsing rules above stand unchanged: the reader delivers the characters and the framing decides when the code is complete.
Prevention checklist
- End every scanner-input pattern with the terminator byte your raw log shows, outside the capture group.
- Run the four-scan test after every pattern, scanner firmware or tool update: shortest code, longest code, and the neighbors of the one that failed.
- Store the raw-byte log with the project so the next engineer matches the same terminator.
- Back up the reader configuration once the framing is settled; the configuration backup guide makes the snapshot routine instead of an afterthought.
More decode and framing fixes sit on the code-reading topic page. If you want a second pair of eyes on the codes, the interface and the framing of a specific line, send the samples through the contact page.
Questions
Why does my barcode pattern work in a regex tester but fail on the scanner input?
A tester applies the pattern to a complete string, so the digit quantifier consumes every digit of H12. The scanner input applies it to a growing buffer and returns on the first match, which two characters already satisfy. The tester asks whether the pattern describes the string; the input asks when the match may fire. Only a terminator in the pattern makes the stream behave like the tester.
Which terminator character belongs at the end of the pattern?
The last byte your scanner actually sends. Keyboard-wedge and most handheld scanners default to Enter, which is the carriage return (ASCII 13); configurable readers offer CR, LF, TAB or a printable suffix such as #. Capture the raw stream once and read its final byte before writing the pattern — the wrong terminator means the match never fires at all.
I set a prefix and suffix on the scanner and now the regex field does nothing — why?
Some input tools treat the prefix and suffix as the message boundary and apply no pattern to the framed data; others frame first and match the regex on the inner string. Log one scan: if the code arrives complete with the pattern field empty, the framing is doing the anchoring and the field is simply unused. Both behaviors deliver a complete code; only the configuration path differs.
Two scanners with different suffixes feed the same input — which pattern do I use?
Terminators differ per device, so one pattern cannot serve both. Either set both scanners to emit the same suffix in their data-output settings, or give each input its own pattern ending in the byte its raw log shows. A shared input with mixed terminators quietly drops every scan whose terminator never arrives — run the four-scan test on each device before production.
Does a longer or fixed-length code change the fix?
No. Length does not tell the engine when the scan ends; a 20-character serial still fires the moment the pattern can be satisfied, which for this alphabet is two characters in. Fixed-length data seems to invite a fixed-length pattern, but a counting pattern rejects short codes that are legitimately in use and still fires before a longer code finishes. The terminator, not the length, closes the match.


