Code readingHow-to

Variable length barcode scanner input: fix it with a suffix

Why variable length barcode input loses the 8th digit, how a scanner suffix character frames the scan, and the regex that matches both 7 and 8 digit codes.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does my regex return only 7 digits on an 8-digit scan?
  2. 02Why doesn't the Enter suffix end the scan as expected?
  3. 03Which suffix character should you program into the scanner?
  4. 04How do you program the suffix into the handheld scanner?
  5. 05What regex matches both 7 and 8 digit codes?
  6. 06Is a prefix character required as well?
  7. 07How do you verify the framing before going live?
  8. 08When is keyboard wedge the wrong interface altogether?
  9. 09Questions

An 8-digit barcode reaches your line and the scanner input that ran for months clips every code to 7 digits. The scanner is not at fault: keyboard-wedge input is a stream of keystrokes with no end-of-scan marker, so a pattern like [0-9]{7,8}$ matches the moment seven digits have arrived. This guide frames variable-length scans with one programmed suffix character, gives the exact pattern for 7- and 8-digit codes, and lists the checks to run before you call the fix done. It applies to any handheld reader in USB keyboard mode feeding a web HMI, a data-entry form, or a test field.

Why does my regex return only 7 digits on an 8-digit scan?

Because the component tests the pattern after every keystroke against the characters that have arrived so far, and [0-9]{7,8}$ succeeds on the seventh digit: the $ anchor matches the end of the buffer, not the end of the scan, so the match fires one digit early.

A regular expression has no "wait for more input" state. When the seventh keystroke lands, the buffer holds exactly seven characters; seven satisfies {7,8}, the buffer ends there, and $ is satisfied. The component posts the value and clears the field, so the eighth digit lands in an empty buffer and is lost or starts a phantom second scan. Greedy matching does not help: greed chooses between alternatives inside one buffer, and seven digits is already a complete match.

Widening the range makes it worse. ([0-9]{7,})$ fires at seven digits for the same reason, and ([0-9]{8})$ never fires on a seven-digit code at all — the reader beeps, the field stays empty, and the operator blames a good label. Here is the trace for the 8-digit code 51203478 under the original pattern:

Keystroke Buffer Result with [0-9]{7,8}$
Digits 1–6 512034 No match — six digits cannot satisfy {7,8}
Digit 7 5120347 Match — 5120347 posts and the buffer clears
Digit 8 8 The scan is already gone

Why doesn't the Enter suffix end the scan as expected?

Because the Enter at the end of a scan is a key event, not a character in the buffer: a browser-based scanner input assembles printable characters, so a newline built in the suffix field — CHR(10) or \n — has nothing to match against.

The keystroke after the last digit is the Enter key itself. Some components treat that event as a commit signal; many drop it as a non-printing key, and then the suffix string never equals any part of the buffer, however you spell the newline. That is why an expression returning CHR(10) appears to do nothing.

Do not fight the encoding. Choose a suffix that is a real printable character and it survives every layer intact: the reader's HID output, the browser's key events, the component buffer, and the plain-text editor you test in.

Which suffix character should you program into the scanner?

Use the pipe | (ASCII 124): it is printable, visible on screen when you test in a plain-text editor, and impossible in any numeric code, so it frames both lengths without colliding with data.

Three rules decide the choice. The character must be impossible in the data — with digit-only codes, every non-digit qualifies. It must be printable, so it passes through HID, browser events, and text buffers unchanged. And one character is enough: a single delimiter is all a frame needs.

Tab also works if you escape it as \t in the pattern, but whitespace is invisible in an editor, which slows every later argument about what the reader sent. Reserve Enter for components that offer an explicit "commit on Enter" option. The printable character is the general solution.

How do you program the suffix into the handheld scanner?

Scan the "add suffix" programming barcode from your reader's manual, then prove the result in a plain-text editor: every scan must end with the pipe before you touch the pattern in the HMI.

  1. Open the programming chapter of your reader's manual — the copy from the manufacturer or its distributor — and find the suffix or "append data" settings.
  2. Scan the programming code that adds a one-character suffix, then enter the pipe | (ASCII 124) as that character.
  3. Scan the code that removes the prefix, so each transmission carries digits and the pipe only.
  4. Power-cycle the reader once and repeat the text check; the setting must survive the reboot.
  5. Scan a 7-digit label and an 8-digit label into the same empty document. Two scans on one line must read 5120347|51203478| — data, pipe, data, pipe, nothing else.
  6. If the manual appends an Enter after the suffix, leave it; the browser drops that non-printing key, and the pattern stops at the pipe.

Any handheld code reader in USB keyboard mode takes this configuration. The wired LS-HCR-0001 is a 1.0 MP reader on USB 2.0, the class of device whose suffix is set by scanning barcodes rather than by software commands. The same reader-side steps apply when the target is an HMI text field; this barcode scanner suffix setup for HMI text entry walkthrough covers the panel end of the link.

Handheld code readersHandheld industrial barcode reader, 1.0 MP, USB 2.0 (LS-HCR-0001)LS-HCR-0001
Resolution
Up to 3 MP
Shutter
Global
Interface
USB
Connection
Wired
$539.00View part

What regex matches both 7 and 8 digit codes?

Match ^([0-9]{7,8})|$ — digits anchored at the front, the pipe as the end-of-scan mark — and the greedy {7,8} then resolves to seven digits for a 7-digit code and eight for an 8-digit code, exactly once, when the suffix keystroke arrives.

[0-9]{7,8}$ fires on the 7th digit, one too early [0-9]{8}$ never fires on a 7-digit code ^([0-9]{7,8})\|$ fires once, on the pipe, at the true length

Three details carry the fix. Escape the pipe as |, because a bare | is the alternation operator. Anchor both ends with ^ and $, so a buffer polluted with stray digits fails outright instead of quietly matching its own tail — a blocked-beam partial followed by a good scan must never post a wrong number. Keep the range at {7,8} rather than widening it: a mislabeled 9-digit code then fails loudly as a no-read instead of passing as noise.

Event Buffer Result with the new pattern
Seven digits arrive 5120347 No match — the pipe has not arrived
Pipe after a 7-digit code 5120347| Match — captures 5120347
Eight digits arrive 51203478 No match
Pipe after an 8-digit code 51203478| Match — captures 51203478

If your component exposes its own suffix field and strips it before matching, you can set the pipe there and match ^[0-9]{7,8}$ on the value alone — appending scans in an HMI scanner input component covers that component-side setting. The in-pattern form works everywhere and keeps the whole frame visible in one line, so prefer it.

Is a prefix character required as well?

No — a suffix alone frames variable-length codes, because the only missing information is where the scan ends. A prefix earns its place only when the field must tell two data formats apart or reject keystrokes typed by hand.

Both of your lengths are digits, so the count plus the delimiter already separates 5120347| from 51203478|. Add a prefix if a second code family — a leading letter, a plant code — starts sharing the field, or if operators can type into the same box and you need proof the string came from a reader. For a single fixed format, prefix and suffix framing for barcode scanner input builds the complete frame; capturing scans with no prefix at all is covered in barcode scanner capture without a prefix.

How do you verify the framing before going live?

Scan one 7-digit code, one 8-digit code, and one deliberately blocked partial, and require exactly three outcomes: 7 digits, 8 digits, and nothing. Any fourth behavior means the suffix or the pattern is still wrong.

  1. Scan the 7-digit label: the HMI value must be exactly seven digits, no pipe.
  2. Scan the 8-digit label into the same field: eight digits, same pattern.
  3. Block the beam mid-scan: no commit. Scan the 8-digit label again at once — the stale partial must not poison the next frame. Set the component's inter-character timeout near 100 ms: a wedge reader spaces its characters a few milliseconds apart, so 100 ms never splits a live scan yet clears fragments long before the next one.
  4. Scan twice back to back: two separate commits, never a 15-digit merge.

Then watch the value-length distribution for one shift. Anything that is not a 7 or an 8 — especially a 14 or a 15 — is a framing hole, not bad data.

When is keyboard wedge the wrong interface altogether?

When lengths keep multiplying past two values, or the same string must reach a PLC and a database, stop wedging: a reader on Ethernet or serial sends every code as a framed packet with its own terminator, and framing stops being your problem.

Three signals say move. More length variants, or alphanumeric codes, put more weight on one delimiter than it should carry. Data bound for a PLC or MES cannot ride keystrokes — barcode reader PLC communication shows the link design. And a wedge has no no-read message: silence after a bad label looks identical to a dead scanner, while a networked reader reports the failed attempt. On those links the reader terminates each transmission itself, almost always with CR and LF (0x0D 0x0A), and the host frames on those two bytes; length stops mattering. The serial wiring is covered in RS232 barcode scanner connection to an embedded host; USB barcode scanner data capture covers staying on USB while leaving wedge mode.

If the handheld form must stay, the wireless LS-HCR-0002 is a 1.0 MP reader with an Ethernet link, so the host frames on the reader's own terminator. For a fixed mount, fixed code readers such as the LS-CRD-0052 — a 1.2 MP model with a 12 mm focal length and an Ethernet interface — hand the host a terminated string instead of keystrokes.

Handheld code readersHandheld industrial barcode reader, 1.0 MP (LS-HCR-0002)LS-HCR-0002
Resolution
Up to 3 MP
Shutter
Global
$539.00View part
Fixed code readersDual aviation plug fixed industrial barcode reader, 1.2 MP, focal length 12 mm (LS-CRD-0052)LS-CRD-0052
Resolution
Up to 3 MP
Shutter
Global
$559.00View part
Code readers & vision sensorsHandheld code readers

Handheld 1D/2D scanners

137 models · from $159.00

Program the pipe, anchor the pattern, run the three-scan check. If the reader itself is the weak link, start from the code reader finder, browse the code reading guides, or send us your mixed-length line.

Questions

Will changing to ([0-9]{8})$ break the 7-digit scans?

Yes, completely. An eight-digit requirement never matches a seven-digit buffer, so those scans never post: the reader beeps, the field stays empty, and the operator starts blaming good labels. Both lengths need one delimiter-based pattern, never a choice between two fixed-count patterns.

Can Tab or Enter do the job instead of the pipe?

Tab can, if your component inserts it as a real character and your pattern escapes it as \t, but whitespace is invisible in a text editor, which slows every later argument about what the reader sent. Enter is the weakest option in browser-based components because it arrives as a key event, not a character. The pipe is printable, visible, and never appears in numeric data.

What happens when someone blocks the beam mid-scan?

The partial digit string has no pipe after it, so the anchored pattern cannot match and nothing posts. The failure is silent but safe — the alternative is a wrong part number. Set the component's inter-character timeout near 100 ms so the stale fragment clears before the next scan arrives.

Do fixed Ethernet or serial readers need the pipe suffix too?

No. A networked reader terminates every transmission itself, almost always with CR and LF (0x0D 0x0A), and the host frames on those two bytes, so code length stops mattering. The pipe trick exists only for keyboard-wedge HID, the one pipeline whose character stream carries no terminator at all.

Why did the 7-digit pattern work for months before this?

Because one fixed length is self-delimiting: seven digits was both the content and the frame, so the digit count alone told the component the scan was complete. Adding a second length destroyed that property, which is the moment a real delimiter becomes necessary rather than optional.