Как обрезать пробелы из переменной 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 ]

3 голосов
/ 16 июня 2012

trim () удаляет пробелы (и вкладки, непечатаемые символы; для простоты я рассматриваю только пробелы). Моя версия решения:

var="$(hg st -R "$path")" # I often like to enclose shell output in double quotes
var="$(echo "${var}" | sed "s/\(^ *\| *\$\)//g")" # This is my suggestion
if [ -n "$var" ]; then
 echo "[${var}]"
fi

Команда «sed» обрезает только начальные и конечные пробелы, но она также может быть передана первой команде, что приводит к:

var="$(hg st -R "$path" | sed "s/\(^ *\| *\$\)//g")"
if [ -n "$var" ]; then
 echo "[${var}]"
fi
3 голосов
/ 04 февраля 2012

Я обнаружил, что мне нужно добавить код из грязного sdiff вывода, чтобы очистить его:

sdiff -s column1.txt column2.txt | grep -F '<' | cut -f1 -d"<" > c12diff.txt 
sed -n 1'p' c12diff.txt | sed 's/ *$//g' | tr -d '\n' | tr -d '\t'

При этом удаляются завершающие пробелы и другие невидимые символы.

2 голосов
/ 07 марта 2014

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

var=`expr "$var" : "^\ *\(.*[^ ]\)\ *$"`

Он удаляет начальные и конечные пробелы и, я считаю, является наиболее простым решением. Не встроенный в Bash, но 'expr' является частью coreutils, поэтому, по крайней мере, не нужны никакие автономные утилиты, такие как sed или AWK .

2 голосов
/ 13 июня 2010

Удаление пробелов в один пробел:

(text) | fmt -su
2 голосов
/ 03 июня 2012

Используйте этот простой Bash параметр расширения :

$ x=" a z     e r ty "
$ echo "START[${x// /}]END"
START[azerty]END
2 голосов
/ 11 октября 2010

Это обрезает несколько пробелов переднего и конечного

whatever=${whatever%% *}

whatever=${whatever#* }

2 голосов
/ 28 февраля 2013
var="  a b  "
echo "$(set -f; echo $var)"

>a b
2 голосов
/ 07 июня 2011

Мне нужно было убрать пробел из скрипта, когда переменная IFS была установлена ​​на что-то другое. Полагаясь на Perl сделал свое дело:

# trim() { echo $1; } # This doesn't seem to work, as it's affected by IFS

trim() { echo "$1" | perl -p -e 's/^\s+|\s+$//g'; }

strings="after --> , <-- before,  <-- both -->  "

OLD_IFS=$IFS
IFS=","
for str in ${strings}; do
  str=$(trim "${str}")
  echo "str= '${str}'"
done
IFS=$OLD_IFS
1 голос
/ 21 сентября 2011

Еще одно решение с модульными тестами , которое обрезает $IFS от стандартного ввода и работает с любым входным разделителем (даже $'\0'):

ltrim()
{
    # Left-trim $IFS from stdin as a single line
    # $1: Line separator (default NUL)
    local trimmed
    while IFS= read -r -d "${1-}" -u 9
    do
        if [ -n "${trimmed+defined}" ]
        then
            printf %s "$REPLY"
        else
            printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
        fi
        printf "${1-\x00}"
        trimmed=true
    done 9<&0

    if [[ $REPLY ]]
    then
        # No delimiter at last line
        if [ -n "${trimmed+defined}" ]
        then
            printf %s "$REPLY"
        else
            printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
        fi
    fi
}

rtrim()
{
    # Right-trim $IFS from stdin as a single line
    # $1: Line separator (default NUL)
    local previous last
    while IFS= read -r -d "${1-}" -u 9
    do
        if [ -n "${previous+defined}" ]
        then
            printf %s "$previous"
            printf "${1-\x00}"
        fi
        previous="$REPLY"
    done 9<&0

    if [[ $REPLY ]]
    then
        # No delimiter at last line
        last="$REPLY"
        printf %s "$previous"
        if [ -n "${previous+defined}" ]
        then
            printf "${1-\x00}"
        fi
    else
        last="$previous"
    fi

    right_whitespace="${last##*[!$IFS]}"
    printf %s "${last%$right_whitespace}"
}

trim()
{
    # Trim $IFS from individual lines
    # $1: Line separator (default NUL)
    ltrim ${1+"$@"} | rtrim ${1+"$@"}
}
0 голосов
/ 07 января 2013

Хотя это не совсем Bash, он будет делать то, что вы хотите, и даже больше:

php -r '$x = trim("  hi there  "); echo $x;'

Если вы хотите сделать его строчным, выполните:

php -r '$x = trim("  Hi There  "); $x = strtolower($x) ; echo $x;'
...