Skip to main content

How to Get Last Character of String

• 2 min read
bash

Quick Answer: Get the Last Character of a String

To extract the last character of a string in Bash, use parameter expansion with negative offset: ${string: -1}. This is the fastest pure-Bash method. Alternatively, use rev with cut or sed for piped input.

Quick Comparison: Last Character Extraction Methods

MethodSpeedBest ForComplexity
Negative parameter expansionFastestVariables, simple extractionSimple
rev + cutVery fastPiped inputModerate
sed ’$!d’FastStreams, patternsModerate
tail -c2Very fastFile streamsSimple
Manual loopSlowerComplex logicModerate

Bottom line: Use negative parameter expansion for variables, use rev | cut for piped input.


Extracting the Last Character

Getting the last character of a string is useful for validation, parsing file extensions, checking line endings, and other text processing tasks. Bash provides several clean methods.

Using Negative Parameter Expansion

The easiest way uses negative offsets in parameter expansion:

#!/bin/bash

string="Hello"

# Get last character
last="${string: -1}"
echo "Last character: $last"
# Output: o

# Get last 3 characters
last_three="${string: -3}"
echo "Last three: $last_three"
# Output: llo

# Note: There's a space after the colon before the minus sign

The syntax ${string: -n} means:

  • -1 = start 1 character from the end
  • Takes all characters from that position to the end

Using rev and cut

Another method reverses the string, gets the first character, then reverses back:

#!/bin/bash

string="Hello"

# Using rev and cut
last=$(echo "$string" | rev | cut -c1 | rev)
echo "Last character: $last"
# Output: o

Length-Based Calculation

Calculate position of the last character:

#!/bin/bash

string="Hello"

# Get length of string
length=${#string}

# Last character is at position length-1
last="${string: -1}"
echo "Last character: $last"
# Output: o

# Get last N characters where N < length
N=2
last_n="${string: -$N}"
echo "Last $N characters: $last_n"
# Output: lo

Comparing Methods

Different approaches with performance implications:

#!/bin/bash

text="Programming"

# Method 1: Negative offset (fastest - no subshell)
last="${text: -1}"

# Method 2: Using rev (slower - spawns subshell)
last=$(echo "$text" | rev | cut -c1 | rev)

# Method 3: Using length calculation
last_pos=$((${#text} - 1))
last="${text:$last_pos:1}"

# All produce: g
echo "$last"

Practical Example: File Extension Extraction

#!/bin/bash

check_extension() {
  local filename="$1"
  local last_char="${filename: -1}"

  if [ "$last_char" = "/" ]; then
    echo "This is a directory path"
  else
    echo "This is a file"
  fi
}

check_extension "document.txt"    # Output: This is a file
check_extension "/home/user/"     # Output: This is a directory path

Getting Last N Characters

Extract any number of trailing characters:

#!/bin/bash

string="example.txt"

# Last character
echo "${string: -1}"      # t

# Last 3 characters
echo "${string: -3}"      # txt

# Last 4 characters
echo "${string: -4}"      # .txt

# Last 8 characters
echo "${string: -8}"      # ample.txt

Real-World Example: Validate Line Endings

#!/bin/bash

process_file() {
  local filename="$1"
  local line_count=0
  local bad_endings=0

  while IFS= read -r line || [[ -n "$line" ]]; do
    ((line_count++))

    # Get last character
    last_char="${line: -1}"

    # Check for control characters
    if [[ "$last_char" == $'\r' ]]; then
      echo "Line $line_count: Windows line ending detected"
      ((bad_endings++))
    fi
  done < "$filename"

  echo "Total lines: $line_count, Bad endings: $bad_endings"
}

process_file "myfile.txt"

Removing Last Character

Strip the last character from a string:

#!/bin/bash

string="Hello!"

# Get all but last character
without_last="${string: 0: -1}"
echo "Without last character: $without_last"
# Output: Hello

# This works too (get length - 1 characters)
length=${#string}
without_last="${string:0: $((length - 1))}"
echo "Without last character: $without_last"
# Output: Hello

Real-World Example: Strip Trailing Slash

#!/bin/bash

normalize_path() {
  local path="$1"
  local last="${path: -1}"

  # Remove trailing slash if present
  if [ "$last" = "/" ]; then
    path="${path: 0: -1}"
  fi

  echo "$path"
}

# Usage
normalize_path "/home/user/"       # Output: /home/user
normalize_path "/home/user"        # Output: /home/user
normalize_path "/tmp/"             # Output: /tmp

Handling Edge Cases

What if the string is very short?

#!/bin/bash

get_last_safe() {
  local string="$1"

  # Check if string is empty
  if [ -z "$string" ]; then
    echo "ERROR: String is empty"
    return 1
  fi

  # Check if string is single character
  if [ ${#string} -eq 1 ]; then
    echo "$string"
    return 0
  fi

  # Get last character
  echo "${string: -1}"
  return 0
}

# Test cases
get_last_safe "Hello"      # Output: o
get_last_safe "A"          # Output: A
get_last_safe ""           # Output: ERROR: String is empty

Practical Example: Validate URL Format

#!/bin/bash

validate_url() {
  local url="$1"
  local last_char="${url: -1}"

  # Basic validation - shouldn't end with slash for most URLs
  if [ "$last_char" = "/" ]; then
    echo "WARNING: URL ends with slash"
  fi

  # Check if domain has extension
  if [[ "$url" =~ \.[a-z]{2,}/?$ ]]; then
    echo "URL looks valid"
    return 0
  else
    echo "URL looks invalid"
    return 1
  fi
}

validate_url "https://example.com"       # Valid
validate_url "https://example.com/"      # Valid but warns
validate_url "https://example"           # Invalid

Performance Comparison

#!/bin/bash

# Test string
string="The Quick Brown Fox Jumps"

# Method 1: Negative offset (FASTEST)
echo "Method 1: Negative offset"
time for ((i=0; i<10000; i++)); do
  last="${string: -1}"
done

# Method 2: Using rev (SLOWER)
echo "Method 2: Using rev"
time for ((i=0; i<10000; i++)); do
  last=$(echo "$string" | rev | cut -c1 | rev)
done

Negative offset is significantly faster because it doesn’t spawn a subshell.

Important Notes

  • Use the syntax ${string: -n} with a SPACE after the colon
  • Without the space, Bash interprets it differently
  • Negative offsets count from the end (-1 is last, -2 is second-to-last)
  • Empty strings return empty (no error)
  • This works with any string, including special characters

Quick Reference

# Get last character
last="${string: -1}"

# Get last N characters
last_n="${string: -5}"

# Remove last character
without_last="${string: 0: -1}"

# Check last character
if [ "${string: -1}" = "!" ]; then
  echo "Exclamation at end"
fi

# Using rev method
last=$(echo "$string" | rev | cut -c1 | rev)

Summary

Extracting the last character using ${string: -1} is the fastest and simplest method in Bash. Use this technique for parsing file extensions, validating input formats, and cleaning up trailing characters. Remember the space after the colon - it’s essential for the correct syntax.