How to trim whitespace from a Bash variable?

后端 未结 30 2163
星月不相逢
星月不相逢 2020-11-22 06:09

I have a shell script with this code:

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

But the conditional code always ex

相关标签:
30条回答
  • 2020-11-22 06:23

    Let's define a variable containing leading, trailing, and intermediate whitespace:

    FOO=' test test test '
    echo -e "FOO='${FOO}'"
    # > FOO=' test test test '
    echo -e "length(FOO)==${#FOO}"
    # > length(FOO)==16
    

    How to remove all whitespace (denoted by [:space:] in tr):

    FOO=' test test test '
    FOO_NO_WHITESPACE="$(echo -e "${FOO}" | tr -d '[:space:]')"
    echo -e "FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
    # > FOO_NO_WHITESPACE='testtesttest'
    echo -e "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}"
    # > length(FOO_NO_WHITESPACE)==12
    

    How to remove leading whitespace only:

    FOO=' test test test '
    FOO_NO_LEAD_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//')"
    echo -e "FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
    # > FOO_NO_LEAD_SPACE='test test test '
    echo -e "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}"
    # > length(FOO_NO_LEAD_SPACE)==15
    

    How to remove trailing whitespace only:

    FOO=' test test test '
    FOO_NO_TRAIL_SPACE="$(echo -e "${FOO}" | sed -e 's/[[:space:]]*$//')"
    echo -e "FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
    # > FOO_NO_TRAIL_SPACE=' test test test'
    echo -e "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}"
    # > length(FOO_NO_TRAIL_SPACE)==15
    

    How to remove both leading and trailing spaces--chain the seds:

    FOO=' test test test '
    FOO_NO_EXTERNAL_SPACE="$(echo -e "${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
    echo -e "FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
    # > FOO_NO_EXTERNAL_SPACE='test test test'
    echo -e "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}"
    # > length(FOO_NO_EXTERNAL_SPACE)==14
    

    Alternatively, if your bash supports it, you can replace echo -e "${FOO}" | sed ... with sed ... <<<${FOO}, like so (for trailing whitespace):

    FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"
    
    0 讨论(0)
  • 2020-11-22 06:23

    From Bash Guide section on globbing

    To use an extglob in a parameter expansion

     #Turn on extended globbing  
    shopt -s extglob  
     #Trim leading and trailing whitespace from a variable  
    x=${x##+([[:space:]])}; x=${x%%+([[:space:]])}  
     #Turn off extended globbing  
    shopt -u extglob  
    

    Here's the same functionality wrapped in a function (NOTE: Need to quote input string passed to function):

    trim() {
        # Determine if 'extglob' is currently on.
        local extglobWasOff=1
        shopt extglob >/dev/null && extglobWasOff=0 
        (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
        # Trim leading and trailing whitespace
        local var=$1
        var=${var##+([[:space:]])}
        var=${var%%+([[:space:]])}
        (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
        echo -n "$var"  # Output trimmed string.
    }
    

    Usage:

    string="   abc def ghi  ";
    #need to quote input-string to preserve internal white-space if any
    trimmed=$(trim "$string");  
    echo "$trimmed";
    

    If we alter the function to execute in a subshell, we don't have to worry about examining the current shell option for extglob, we can just set it without affecting the current shell. This simplifies the function tremendously. I also update the positional parameters "in place" so I don't even need a local variable

    trim() {
        shopt -s extglob
        set -- "${1##+([[:space:]])}"
        printf "%s" "${1%%+([[:space:]])}" 
    }
    

    so:

    $ s=$'\t\n \r\tfoo  '
    $ shopt -u extglob
    $ shopt extglob
    extglob         off
    $ printf ">%q<\n" "$s" "$(trim "$s")"
    >$'\t\n \r\tfoo  '<
    >foo<
    $ shopt extglob
    extglob         off
    
    0 讨论(0)
  • 2020-11-22 06:25

    I've seen scripts just use variable assignment to do the job:

    $ xyz=`echo -e 'foo \n bar'`
    $ echo $xyz
    foo bar
    

    Whitespace is automatically coalesced and trimmed. One has to be careful of shell metacharacters (potential injection risk).

    I would also recommend always double-quoting variable substitutions in shell conditionals:

    if [ -n "$var" ]; then
    

    since something like a -o or other content in the variable could amend your test arguments.

    0 讨论(0)
  • 2020-11-22 06:28

    Use AWK:

    echo $var | awk '{gsub(/^ +| +$/,"")}1'
    
    0 讨论(0)
  • 2020-11-22 06:29

    With Bash's extended pattern matching features enabled (shopt -s extglob), you can use this:

    {trimmed##*( )}

    to remove an arbitrary amount of leading spaces.

    0 讨论(0)
  • 2020-11-22 06:30

    You can use old-school tr. For example, this returns the number of modified files in a git repository, whitespaces stripped.

    MYVAR=`git ls-files -m|wc -l|tr -d ' '`
    
    0 讨论(0)
提交回复
热议问题