Skip to content
shellhacks.dev
Shell Scripting

Get a substring in POSIX sh

POSIX sh has no ${v:2:3}. Build a substring from two prefix strips instead, or use cut when a subprocess is acceptable. Both run in dash.

1 min read
Summarize in AI

Bash gives you ${v:2:3}, but under #!/bin/sh on Debian the same line is a syntax error.

Shell
v=abcdefgh
echo "${v:2:3}"
Text
main.sh: 2: Bad substitution
Shell
v=abcdefgh
rest=${v#??}
echo "${rest%"${rest#???}"}"
printf '%s\n' "$v" | cut -c3-5
Text
cde
cde

The first run shows dash rejecting the offset syntax. The second works only with operators that are in POSIX parameter expansion: ${v#??} drops the first two characters, ${rest#???} leaves everything after the first three, and removing that from the end of rest leaves exactly three characters. cut -c is the simpler spelling when a fork is fine.

The pure expansion version is hard to read, so wrap it in a function with a comment. GNU cut -c counts bytes, not characters, so multibyte text can be cut in the middle of a character.

Share

More snippets

Shell Scripting

Test for a prefix without double brackets

Test for a prefix in POSIX sh with a case pattern such as release-*), which works in dash and every other shell where double brackets are a syntax error.

1 min read
Shell Scripting

Check if a command exists in POSIX sh

Check that a command exists with command -v in POSIX sh. It is a builtin, it sees functions and builtins, and which does not.

1 min read
Shell Scripting

Replace an array with positional parameters

POSIX sh has no arrays, but set -- a b c turns the positional parameters into one, and "$@" expands each element as its own word without splitting.

1 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.