Как обрезать пробелы из переменной Bash? - PullRequest
781 голосов
/ 16 декабря 2008

У меня есть сценарий оболочки с этим кодом:

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

Но условный код всегда выполняется, потому что hg st всегда печатает хотя бы один символ новой строки.

  • Есть ли простой способ убрать пробелы из $var (например, trim() в PHP )?

или

  • Существует ли стандартный способ решения этой проблемы?

Я мог бы использовать sed или AWK , но я хотел бы думать, что есть более элегантное решение этой проблемы.

Ответы [ 41 ]

5 голосов
/ 08 июня 2011

Вот функция trim (), которая урезает и нормализует пробел

#!/bin/bash
function trim {
    echo $*
}

echo "'$(trim "  one   two    three  ")'"
# 'one two three'

И еще один вариант, использующий регулярные выражения.

#!/bin/bash
function trim {
    local trimmed="$@"
    if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
    then 
        trimmed=${BASH_REMATCH[1]}
    fi
    echo "$trimmed"
}

echo "'$(trim "  one   two    three  ")'"
# 'one   two    three'
5 голосов
/ 06 июля 2012

Чтобы удалить пробелы и табуляции слева направо, введите:

echo "     This is a test" | sed "s/^[ \t]*//"

cyberciti.biz / советы / удалить лидирующим-пространства-из-перед-на-каждый-word.html

5 голосов
/ 06 ноября 2009

Использовать AWK:

echo $var | awk '{gsub(/^ +| +$/,"")}1'
4 голосов
/ 28 апреля 2014

Это самый простой метод, который я видел. Он использует только Bash, это всего несколько строк, регулярное выражение простое и соответствует всем формам пробелов:

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

Вот пример сценария для тестирования:

test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t  \n ")

echo "Let's see if this works:"
echo
echo "----------"
echo -e "Testing:${test} :Tested"  # Ugh!
echo "----------"
echo
echo "Ugh!  Let's fix that..."

if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]]
then 
    test=${BASH_REMATCH[1]}
fi

echo
echo "----------"
echo -e "Testing:${test}:Tested"  # "Testing:Spaces and tabs and newlines be gone!"
echo "----------"
echo
echo "Ah, much better."
4 голосов
/ 29 мая 2013

Это удалит все пробелы из вашей строки,

 VAR2="${VAR2//[[:space:]]/}"

/ заменяет первое вхождение и // все вхождения пробелов в строке. То есть все пробелы заменяются - ничего

4 голосов
/ 03 ноября 2011

Это не имеет проблемы с нежелательным смещением, также внутреннее пустое пространство не изменяется (при условии, что для $IFS установлено значение по умолчанию, равное ' \t\n').

Он читает до первой новой строки (и не включает ее) или до конца строки, в зависимости от того, что наступит раньше, и удаляет любое сочетание начального и конечного пробела и символов \t. Если вы хотите сохранить несколько строк (а также убрать начальные и конечные переводы строк), используйте read -r -d '' var << eof вместо этого; заметьте, однако, что если ваш ввод содержит \neof, он будет обрезан непосредственно перед этим. (Другие формы пробелов, а именно \r, \f и \v, не удалены, даже если вы добавите их в $ IFS.)

read -r var << eof
$var
eof
3 голосов
/ 02 декабря 2011
#!/bin/bash

function trim
{
    typeset trimVar
    eval trimVar="\${$1}"
    read trimVar << EOTtrim
    $trimVar
EOTtrim
    eval $1=\$trimVar
}

# Note that the parameter to the function is the NAME of the variable to trim, 
# not the variable contents.  However, the contents are trimmed.


# Example of use:
while read aLine
do
    trim aline
    echo "[${aline}]"
done < info.txt



# File info.txt contents:
# ------------------------------
# ok  hello there    $
#    another  line   here     $
#and yet another   $
#  only at the front$
#$



# Output:
#[ok  hello there]
#[another  line   here]
#[and yet another]
#[only at the front]
#[]
3 голосов
/ 12 июля 2015

Использование:

trim() {
    local orig="$1"
    local trmd=""
    while true;
    do
        trmd="${orig#[[:space:]]}"
        trmd="${trmd%[[:space:]]}"
        test "$trmd" = "$orig" && break
        orig="$trmd"
    done
    printf -- '%s\n' "$trmd"
}
  • Работает со всеми видами пробелов, включая перевод строки
  • Не нужно изменять Shopt.
  • Сохраняет внутри пробела, включая перевод строки.

Юнит-тест (для просмотра вручную):

#!/bin/bash

. trim.sh

enum() {
    echo "   a b c"
    echo "a b c   "
    echo "  a b c "
    echo " a b c  "
    echo " a  b c  "
    echo " a  b  c  "
    echo " a      b  c  "
    echo "     a      b  c  "
    echo "     a  b  c  "
    echo " a  b  c      "
    echo " a  b  c      "
    echo " a N b  c  "
    echo "N a N b  c  "
    echo " Na  b  c  "
    echo " a  b  c N "
    echo " a  b  c  N"
}

xcheck() {
    local testln result
    while IFS='' read testln;
    do
        testln=$(tr N '\n' <<<"$testln")
        echo ": ~~~~~~~~~~~~~~~~~~~~~~~~~ :" >&2
        result="$(trim "$testln")"
        echo "testln='$testln'" >&2
        echo "result='$result'" >&2
    done
}

enum | xcheck
3 голосов
/ 15 ноября 2010

Я создал следующие функции. Я не уверен, насколько переносим printf, но прелесть этого решения в том, что вы можете точно указать, что такое «пробел», добавив больше кодов символов.

    iswhitespace()
    {
        n=`printf "%d\n" "'$1'"`
        if (( $n != "13" )) && (( $n != "10" )) && (( $n != "32" )) && (( $n != "92" )) && (( $n != "110" )) && (( $n != "114" )); then
            return 0
        fi
        return 1
    }

    trim()
    {
        i=0
        str="$1"
        while (( i < ${#1} ))
        do
            char=${1:$i:1}
            iswhitespace "$char"
            if [ "$?" -eq "0" ]; then
                str="${str:$i}"
                i=${#1}
            fi
            (( i += 1 ))
        done
        i=${#str}
        while (( i > "0" ))
        do
            (( i -= 1 ))
            char=${str:$i:1}
            iswhitespace "$char"
            if [ "$?" -eq "0" ]; then
                (( i += 1 ))
                str="${str:0:$i}"
                i=0
            fi
        done
        echo "$str"
    }

#Call it like so
mystring=`trim "$mystring"`
3 голосов
/ 08 августа 2014

Python имеет функцию strip(), которая работает идентично PHP trim(), поэтому мы можем просто сделать небольшой встроенный Python, чтобы сделать легко понятную утилиту для этого:

alias trim='python -c "import sys; sys.stdout.write(sys.stdin.read().strip())"'

Это урезает начальные и конечные пробелы (включая переводы строк).

$ x=`echo -e "\n\t   \n" | trim`
$ if [ -z "$x" ]; then echo hi; fi
hi
...