How to Count Characters in a String in Bash
Quick Answer: Get String Length in Bash
To get the length of a string in Bash, use parameter expansion: ${#text}. This returns the number of characters in the variable. It’s the fastest method because it uses built-in Bash functionality with no external commands.
Quick Comparison: String Length Methods
| Method | Speed | Best For | Compatibility |
|---|---|---|---|
| Parameter expansion | Fastest | Simple length checks | All Bash versions |
| wc -c | Very fast | Piped input | All systems |
| awk length() | Very fast | Complex processing | All systems |
| expr | Fast | Legacy systems | All systems |
| printf | Fast | Formatted output | All Bash versions |
Bottom line: Use parameter expansion for maximum speed. Use wc or awk when processing piped data.
Method 1: Parameter Expansion (Recommended)
Parameter expansion ${#variable} is the fastest and cleanest way to get string length. It uses built-in Bash functionality with no external commands or process overhead. When your text is in a variable, this is always your best choice.
Basic String Length
Here’s the fundamental pattern—use a hash symbol before the variable name:
text="Hello"
length=${#text}
echo "$length"
# Output: 5
The # inside the braces tells Bash to return the length instead of the value. This works with any variable containing a string, no matter the content.
Length Directly in Conditions
You can use string length directly in comparisons without storing it first:
password="secret123"
if [ ${#password} -lt 8 ]; then
echo "Password too short"
else
echo "Password is valid"
fi
This checks the length in one step. The comparison operators (-lt, -gt, -eq) work with numeric lengths.
When to Use Parameter Expansion
Use parameter expansion when:
- You have a string in a variable (the common case)
- You need the fastest performance
- You want simplicity and readability
- You’re checking string length in conditions
- You’re validating input length
Avoid it when:
- You’re reading from a pipe (use
wcinstead) - You need complex text processing (use
awk) - The string contains newlines and you want byte count (use
wc)
Method 2: Using wc Command
The wc command counts bytes or characters, useful when reading from pipes or files. It’s an external command, so it’s slower than parameter expansion, but it’s standard across all Unix systems and handles piped input naturally.
Count Characters in Piped Input
When data comes from a pipe, you can use wc -c:
text="Hello"
echo -n "$text" | wc -c
# Output: 5
The -n flag in echo prevents adding a newline, so wc -c counts only the actual text. Without -n, you’d count the newline too.
Count Bytes vs Characters
For ASCII strings, characters and bytes are the same. But for Unicode, be careful:
text="Hëllo" # Contains non-ASCII character
echo -n "$text" | wc -c # Counts bytes (6 on UTF-8)
echo ${#text} # Counts characters (5)
Parameter expansion counts characters; wc -c counts bytes. For Unicode strings, use parameter expansion to count actual characters.
When to Use wc
Use wc when:
- Reading from pipes or files (more natural)
- You need compatibility with non-Bash scripts
- You’re counting bytes specifically
- You’re processing file input
Skip it when:
- Working with variables (parameter expansion is faster)
- You need Unicode character count (use parameter expansion)
Method 3: Using awk
awk is powerful when you need length information as part of complex text processing. It has a built-in length() function and integrates naturally with data transformation.
Get Length with awk
text="Hello"
length=$(echo "$text" | awk '{print length}')
echo "$length"
# Output: 5
The length function (without parentheses) returns the length of the current line. This is useful when you’re already using awk to process text.
Combine Length with Other Processing
Where awk really shines is when you need length as part of broader processing:
text="apple"
result=$(echo "$text" | awk '{print "Word: " $0 ", Length: " length}')
echo "$result"
# Output: Word: apple, Length: 5
You’re getting length and building a formatted output in one command.
When to Use awk
Use awk when:
- You’re already processing text with awk
- You need length combined with other operations
- You’re processing structured data (CSV, etc.)
- You want to work with fields and records
Avoid it when:
- Simple length check needed (parameter expansion is faster)
- Reading from variables (parameter expansion is simpler)
Practical Examples
Example 1: Validate Password Length
#!/bin/bash
password="$1"
min_length=8
max_length=32
if [ ${#password} -lt $min_length ]; then
echo "Password too short (minimum $min_length characters)"
exit 1
elif [ ${#password} -gt $max_length ]; then
echo "Password too long (maximum $max_length characters)"
exit 1
else
echo "Password length is valid"
fi
This validates that a password meets length requirements. Simple, clear, and fast.
Example 2: Check if String is Empty
#!/bin/bash
text="$1"
if [ ${#text} -eq 0 ]; then
echo "Error: No input provided"
exit 1
else
echo "Received: $text (${#text} characters)"
fi
A common pattern for validating that required input was provided.
Example 3: Extract File Extension Using Length
#!/bin/bash
filename="document.txt"
length=${#filename}
# Get last 4 characters (the extension)
extension="${filename:$((length-4))}"
echo "Extension: $extension"
# Output: Extension: .txt
Using length to calculate the position for extracting the extension. The ${string:start:length} syntax uses the length to find where the extension starts.
Example 4: Truncate String to Maximum Length
#!/bin/bash
text="This is a very long string that needs truncating"
max_length=20
if [ ${#text} -gt $max_length ]; then
truncated="${text:0:$max_length}..."
echo "Truncated: $truncated"
else
echo "Text: $text"
fi
Check if text exceeds a limit, and if so, truncate it. This is useful for display purposes.
Example 5: Count Array Elements
#!/bin/bash
# Array length uses similar syntax
fruits=(apple banana orange mango kiwi)
echo "Number of fruits: ${#fruits[@]}"
# Output: Number of fruits: 5
# You can also get specific array element length
echo "Length of first fruit: ${#fruits[0]}"
# Output: Length of first fruit: 5
For arrays, ${#array[@]} gives the number of elements, while ${#array[i]} gives the length of an element.
Example 6: Count Occurrences of a Character
#!/bin/bash
text="hello world"
# Remove all non-'o' characters, then count length
count=${text//[!o]/}
num_o=${#count}
echo "The letter 'o' appears $num_o times"
# Output: The letter 'o' appears 2 times
This clever technique uses parameter expansion to remove everything except the character you’re counting, then gets the length of what remains.
Example 7: Validate Username Format
#!/bin/bash
username="$1"
min_length=3
max_length=20
if [ ${#username} -lt $min_length ]; then
echo "Username too short (minimum $min_length characters)"
exit 1
elif [ ${#username} -gt $max_length ]; then
echo "Username too long (maximum $max_length characters)"
exit 1
elif [[ ! "$username" =~ ^[a-zA-Z0-9_]+$ ]]; then
echo "Username contains invalid characters"
exit 1
else
echo "Username is valid"
fi
Combine length checks with pattern validation for complete input validation.
Quick Reference
# Get string length
${#text}
# Check if empty
[ ${#text} -eq 0 ]
# Check minimum length
[ ${#text} -lt 8 ]
# Check maximum length
[ ${#text} -gt 20 ]
# Get array length
${#array[@]}
# Get specific element length
${#array[0]}
# Using in piped input
echo "$text" | wc -c
# Count character occurrences
count=${text//[!x]/} # Count 'x'
${#count}
Summary
Use parameter expansion ${#variable} for string length in 99% of cases. It’s the fastest, clearest way to get the length of a string stored in a variable. The syntax is simple, the performance is optimal, and it handles Unicode characters correctly. Only reach for wc when you’re working with piped input or file data, and use awk when you’re already processing complex text.