NeuroAgent

How to Trim Whitespace in Bash Variables

Learn multiple methods to trim whitespace from Bash variables efficiently. Discover parameter expansion, read command, sed, and tr solutions for clean shell scripting.

Question

How to trim whitespace from a Bash variable?

I have a shell script with this code:

bash
var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

But the conditional code always executes, because hg st always prints at least one newline character.

Is there a simple way to strip whitespace from $var (like trim() in PHP)?

Or is there a standard way of dealing with this issue?

I could use sed or AWK, but I’d like to think there is a more elegant solution to this problem.

NeuroAgent

To trim whitespace from a Bash variable, you can use several methods including parameter expansion, sed, awk, or read command. The most elegant solution for your hg st issue would be to use parameter expansion patterns or the read command to strip whitespace, then check if the resulting variable is empty.


Contents


Understanding the Problem with hg st

The issue you’re experiencing occurs because the hg st command (Mercurial status) always outputs at least one newline character, even when there are no changes to report. This makes Bash treat the variable as non-empty, causing your conditional [ -n "$var" ] to always execute.

As noted in the research, this is a common problem when dealing with commands that output newlines or whitespace characters. Your original code:

bash
var=`hg st -R "$path"`
if [ -n "$var" ]; then
    echo $var
fi

Will always print the output because var contains at least a newline character, making it non-empty to Bash.


Using Parameter Expansion to Trim Whitespace

Bash provides powerful parameter expansion capabilities that can be used to trim whitespace without external commands. This is often the most elegant solution:

Basic Trimming Patterns

bash
# Remove leading whitespace
var="${var#"${var%%[![:space:]]*}"}"
# Remove trailing whitespace  
var="${var%"${var##*[![:space:]]}"}"

More Readable Version with extglob

bash
shopt -s extglob
var="${var##+( )}"    # Remove leading whitespace
var="${var%%+( )}"    # Remove trailing whitespace
shopt -u extglob

Comprehensive Trimming Function

bash
trim() {
    local var="$1"
    # Remove leading whitespace
    var="${var#"${var%%[![:space:]]*}"}"
    # Remove trailing whitespace
    var="${var%"${var##*[![:space:]]}"}"
    printf '%s' "$var"
}

This approach is very efficient as it uses only Bash built-in features without spawning external processes source.


Using read Command for Whitespace Removal

The read command can be used to strip all leading and trailing whitespace from a variable:

bash
var="   hello world   "
read -r var <<< "$var"
echo "='$var='"  # Output: '=hello world='

For your specific hg st issue:

bash
var=`hg st -R "$path"`
read -r var <<< "$var"
if [ -n "$var" ]; then
    echo "$var"
fi

This works because read automatically strips leading and trailing whitespace characters (spaces and tabs) when reading into a variable. However, note that this method may not preserve internal whitespace exactly as-is source.


Using sed for Trimming

sed is a powerful tool for text manipulation and can be used to trim whitespace:

Single-line trimming

bash
var="   test string   "
var=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "$var")

Function approach

bash
trim_sed() {
    local var="$1"
    var=$(sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' <<< "$var")
    printf '%s' "$var"
}

For multi-line variables, you can use GNU Sed’s -z option:

bash
trim_multiline_sed() {
    local var="$1"
    var=$(printf '%s' "$var" | sed -z 's/^[[:space:]]*//' | sed -z 's/[[:space:]]*$//')
    printf '%s' "$var"
}

The sed approach is versatile but may be slower than parameter expansion due to the external process overhead source.


Using tr for Simple Whitespace Removal

The tr command can be used for simple whitespace removal, though it’s more suited for removing specific characters rather than trimming:

bash
# Remove all whitespace including newlines
var=$(echo -n "$var" | tr -d '[:space:]')

# Remove newlines only
var=$(echo -n "$var" | tr -d '\n')

For your hg st issue, you could simply remove the newline:

bash
var=$(hg st -R "$path" | tr -d '\n')
if [ -n "$var" ]; then
    echo "$var"
fi

This approach works well but removes all newlines, which might not be what you want if you need to preserve line breaks source.


Checking if Variable is Empty After Trimming

After trimming, you need to properly check if the variable is empty. Here are several approaches:

Using -z test

bash
trimmed_var=$(trim "$var")
if [ -z "$trimmed_var" ]; then
    echo "Variable is empty after trimming"
fi

Using pattern matching

bash
# Check if variable contains only whitespace
if [[ $var =~ ^[[:space:]]*$ ]]; then
    echo "Variable is empty or contains only whitespace"
fi

Using parameter expansion

bash
if [ -n "${var// /[[:space:]]}" ]; then
    echo "Variable contains non-whitespace characters"
fi

These methods help you accurately determine if your variable contains meaningful content after trimming source.


Complete Solution for Your hg st Issue

Here’s a complete solution using parameter expansion:

bash
#!/bin/bash

path="/your/repo/path"

# Get the status and trim whitespace
var=$(hg st -R "$path")
var="${var#"${var%%[![:space:]]*}"}"  # Remove leading whitespace
var="${var%"${var##*[![:space:]]}"}"  # Remove trailing whitespace

# Check if variable is meaningful
if [ -n "$var" ]; then
    echo "$var"
else
    echo "No changes detected"
fi

Or using the read method:

bash
#!/bin/bash

path="/your/repo/path"

# Get status and trim using read
read -r var <<< "$(hg st -R "$path")"

if [ -n "$var" ]; then
    echo "$var"
else
    echo "No changes detected"
fi

Both solutions will properly handle the case where hg st outputs only newlines source.


Performance Comparison

Different methods have different performance characteristics:

Method Speed Portability Features
Parameter expansion Fastest Bash only Limited features
read command Fast POSIX Good for basic trimming
sed Medium Universal Powerful but slower
tr Fast Universal Good for simple removal

For shell scripts where performance matters, parameter expansion is generally the best choice. For portability across different shells, the read method is excellent source.


Handling Multi-line Variables

If your variable might contain multiple lines and you need to trim each line individually, you can use a loop:

bash
trim_multiline() {
    local var="$1"
    local result=""
    while IFS= read -r line; do
        # Trim each line
        line="${line#"${line%%[![:space:]]*}"}"
        line="${line%"${line##*[![:space:]]}"}"
        # Add non-empty lines to result
        if [ -n "$line" ]; then
            result+="$line"$'\n'
        fi
    done <<< "$var"
    printf '%s' "$result"
}

This preserves the line structure while trimming whitespace from each line source.


Conclusion

Trimming whitespace in Bash can be accomplished through several methods, each with its own advantages:

  1. Parameter expansion is the most elegant and efficient method, using only Bash built-ins
  2. read command provides a simple, portable solution for basic trimming
  3. sed offers powerful pattern matching for complex cases
  4. tr is excellent for simple character removal

For your specific hg st issue, either parameter expansion or the read method would be the most appropriate solution. Both will effectively remove the trailing newline that’s causing your conditional to always execute.

The key takeaway is that while Bash doesn’t have a built-in trim() function like PHP, the shell’s parameter expansion capabilities provide powerful tools for string manipulation that are both efficient and elegant.


Sources

  1. Stack Overflow - How to trim whitespace from a Bash variable
  2. Baeldung on Linux - How to Trim Whitespace From a Bash Variable
  3. nixCraft - Bash Shell Remove & Trim White Spaces From String / Variable
  4. Reddit r/bash - Remove leading and trailing spaces from a variable
  5. Unix & Linux Stack Exchange - How do I trim leading and trailing whitespace from each line?
  6. Greg’s Wiki - BashFAQ/067
  7. ioflood - How to Trim Whitespace In Bash Shell Scripts
  8. Goran et al. - Trimming a string with Bash