How to Get Last Character of String
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
| Method | Speed | Best For | Complexity |
|---|---|---|---|
| Negative parameter expansion | Fastest | Variables, simple extraction | Simple |
| rev + cut | Very fast | Piped input | Moderate |
| sed ’$!d’ | Fast | Streams, patterns | Moderate |
| tail -c2 | Very fast | File streams | Simple |
| Manual loop | Slower | Complex logic | Moderate |
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.