Bash Scripting
Programming
Code Snippets
Substrings
Unix Commands

Extract substring in Bash

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Bash can slice strings directly with parameter expansion, so you usually do not need cut, awk, or expr for simple substring work. The built-in syntax is faster, easier to read once you know the rules, and portable across normal Bash environments.

Slice by Offset and Length

The basic form is variable:offset:length inside parameter expansion. Offsets are zero-based, so position 0 means the first character.

bash
1text="deployment-ready"
2part=${text:0:10}
3
4echo "$part"

The output is:

text
deployment

If you omit the length, Bash returns everything from the offset to the end.

bash
1text="deployment-ready"
2suffix=${text:11}
3
4echo "$suffix"

That prints ready.

This form is good when the string format is fixed, such as a prefix, a date stamp, or a known identifier layout.

Use Negative Offsets Carefully

Bash also supports counting backward from the end of the string. The common detail people miss is the space before a negative offset.

bash
1file="archive.tar.gz"
2extension=${file: -2}
3
4echo "$extension"

That returns gz.

You can combine a negative offset with a length as well.

bash
1file="archive.tar.gz"
2segment=${file: -6:3}
3
4echo "$segment"

That prints tar.

The spacing matters because without it Bash can interpret the expression differently. If you find the syntax hard to scan, assign the string to a named variable first and keep the slice simple.

Pattern Removal Often Solves the Real Problem

Not every extraction job should use character positions. When strings are structured by delimiters, Bash pattern removal is often safer.

bash
1path="/srv/app/config.yaml"
2filename=${path##*/}
3basename=${filename%.yaml}
4
5echo "$filename"
6echo "$basename"

This uses two different operators:

  • '## removes the longest matching prefix'
  • '% removes the shortest matching suffix'

For file names, URLs, and extension handling, pattern removal is usually more maintainable than hard-coded indexes. If the length of the directory path changes, the pattern version still works.

Extract from Script Input

A common real-world case is taking part of a positional argument. The safest pattern is to copy the argument into a normal variable and slice that variable.

bash
1#!/usr/bin/env bash
2value="$1"
3code=${value:0:4}
4
5echo "$code"

This keeps the script readable and avoids confusion around special parameter behavior. It also makes it easier to add validation, such as checking that the argument is long enough before slicing.

Compare Built-Ins with External Tools

Older shell examples often call external commands for substring extraction.

bash
text="deployment-ready"
printf '%s\n' "$text" | cut -c1-10

This works, but it starts another process. In a tiny script that does not matter much, but inside loops or frequently called helpers, built-in expansion is cleaner and faster.

Use an external command only when the operation is no longer simple slicing. For example, field-based parsing with a delimiter may be better served by cut -d, and complex reshaping may be better served by awk.

Quote the Result

Substring extraction does not remove the need for quoting. If the extracted value contains spaces or wildcard characters, unquoted expansion can trigger word splitting or pathname expansion.

bash
1label="build candidate"
2first_word=${label:0:5}
3
4echo "$first_word"

Keep the expansion quoted unless you explicitly want shell splitting behavior.

Common Pitfalls

  • Forgetting that Bash offsets are zero-based and slicing one character too early or too late.
  • Writing a negative offset without the required space, as in ${var: -3}.
  • Using fixed numeric positions when the underlying data is really delimiter-based and better handled with %, %%, #, or ##.
  • Calling cut or expr for ordinary Bash slicing and making scripts noisier than they need to be.
  • Expanding the extracted value unquoted and introducing word-splitting bugs.

Summary

  • Use Bash parameter expansion for most substring tasks.
  • '${var:offset:length} is the standard slicing form.'
  • Omitting the length returns the remainder of the string.
  • Negative offsets work, but the spacing is easy to get wrong.
  • Pattern removal operators are often better than numeric slicing for structured strings.

Course illustration
Course illustration

All Rights Reserved.