Class 24 of 37 • Advance Shell Script \t\t\t\t

String Manipulation in Linux Shell Scripting - Substrings, Length & Regex

Linux Bash supports a powerful set of built-in string manipulation operations. While older Bourne shell scripts frequently invoked external tools like expr or awk, modern Bash provides instant Parameter Expansion with the ${} syntax that executes directly within the shell memory without launching child subshells.

1. Finding String Length

The fastest and cleanest way to calculate the length (character count) of a string variable is ${#string}:

#!/bin/bash
# Note: Never put spaces around '=' during variable assignment!
str="Veewom Linux Programming"

# Pure Bash parameter expansion (Recommended - very fast)
len=${#str}
echo "Length using \${#str}: $len"

# Legacy UNIX method using expr (Requires quotes if string contains spaces)
len_expr=$(expr length "$str")
echo "Length using expr: $len_expr"

2. Substring Extraction (Slicing)

Extracting a specific slice of a string is done using ${string:offset:length}, where offset is the 0-based starting index:

Syntax

Description

Example Output

${str:offset}

Extracts from index offset to the end of string.

${str:7} → "Linux Programming"

${str:offset:length}

Extracts length characters starting from index offset.

${str:0:6} → "Veewom"

${str: -N}

Extracts the last N characters from the end (notice leading space!).

${str: -11} → "Programming"

3. Substring Search and Replace

Bash allows pattern-based text replacement without running sed:

#!/bin/bash
msg="I love unix. unix is fast and unix is robust."

# Replace first match: ${var/pattern/replacement}
echo "${msg/unix/Linux}"
# Output: I love Linux. unix is fast and unix is robust.

# Replace ALL matches globally: ${var//pattern/replacement}
echo "${msg//unix/Linux}"
# Output: I love Linux. Linux is fast and Linux is robust.

# Replace only if match occurs at the BEGINNING: ${var/#pattern/replacement}
path="/var/log/syslog"
echo "${path/#\/var/\/tmp}"
# Output: /tmp/log/syslog

# Replace only if match occurs at the END: ${var/%pattern/replacement}
file="report.txt"
echo "${file/%.txt/.pdf}"
# Output: report.pdf

4. Stripping Prefixes and Suffixes (Path Trimming)

System administrators and shell programmers constantly extract filenames or directories from path strings using prefix/suffix removal:

Pattern

Action

Example on filepath="/home/user/code/main.c"

${var#pattern}

Remove shortest match from start (prefix).

${filepath#*/} → "home/user/code/main.c"

${var##pattern}

Remove longest match from start (basename extraction).

${filepath##*/} → "main.c"

${var%pattern}

Remove shortest match from end (strip file extension).

${filepath%.*} → "/home/user/code/main"

${var%%pattern}

Remove longest match from end (dirname extraction).

${filepath%%/*} → "" (removes up to last slash)

5. Changing Case (Uppercase & Lowercase in Bash 4+)

#!/bin/bash
company="Veewom Tech"

# Convert to all UPPERCASE with ^^
echo "${company^^}"    # VEEWOM TECH

# Convert to all lowercase with ,,
echo "${company,,}"    # veewom tech

# Capitalize only the first character with ^
lang="bash"
echo "${lang^}"        # Bash

6. String Comparison & Validation Operators

Operator

Condition Checked

Example

= or ==

Strings are equal

[ "$a" = "$b" ]

!=

Strings are NOT equal

[ "$a" != "$b" ]

-z

String is NULL or length is 0 (Empty)

[ -z "$str" ]

-n

String is NOT null (Has characters)

[ -n "$str" ]

=~

Matches regular expression (in [[ ]])

[[ "$email" =~ ^[A-Za-z0-9._%+-]+@ ]]

Lab Practice: Palindrome String Checker & File Extension Parser

Problem 1: Write a shell script to reverse a string and check whether it is a palindrome.

#!/bin/bash
# palindrome.sh: Check if string is palindrome
read -p "Enter a word or string: " input

len=${#input}
reverse=""

# Loop backwards through characters
for (( i=$len-1; i>=0; i-- )); do
    reverse="$reverse${input:$i:1}"
done

echo "Original string : $input"
echo "Reversed string : $reverse"

if [ "$input" = "$reverse" ]; then
    echo "Result: '$input' IS a Palindrome!"
else
    echo "Result: '$input' is NOT a Palindrome."
fi

Problem 2: Extract the filename without extension and directory path from a full path string:

#!/bin/bash
# path_parser.sh
full_path="/var/www/html/veewom/index.htm"

filename="${full_path##*/}"         # index.htm
basename="${filename%.*}"           # index
extension="${full_path##*.}"        # htm
directory="${full_path%/*}"         # /var/www/html/veewom

echo "Full Path : $full_path"
echo "Directory : $directory"
echo "File Name : $filename"
echo "Base Name : $basename"
echo "Extension : $extension"

Frequently Asked Questions (FAQs)

Use ${#variable_name}. For instance, if name="Linux", ${#name} evaluates directly to 5 without spawning subshell processes.
Use double slash substitution: ${string//search_term/replace_term}. A single slash replaces only the first occurrence.
Use the -z test operator: if [ -z "$str" ]; then echo "String is empty"; fi. Always wrap the variable in double quotes to prevent syntax errors when the variable is unset.
Both strip matches from the beginning (prefix) of the variable. Single # removes the shortest matching pattern, whereas double ## removes the longest matching pattern.

Next Step in Your Linux Learning Path:

Advance to compiled C system programming and process creation in Class 25: Process Management & System Calls.

Continue to Class 25: Process Management & System Calls → Previous: ← Command Line | Full Syllabus

Share Share on Facebook Share on Twitter Share on LinkedIn Pin on Pinterest Share on Stumbleupon Share on Tumblr Share on Reddit Share on Diggit

You may also like this!