我有一个shell脚本与这段代码:

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

但是条件代码总是执行,因为hg st总是打印至少一个换行符。

是否有一个简单的方法从$var中剥离空白(如PHP中的trim())?

or

有没有处理这个问题的标准方法?

我可以使用sed或AWK,但我认为有一个更优雅的解决方案来解决这个问题。


当前回答

剥离一个前导和一个后导空间

trim()
{
    local trimmed="$1"

    # Strip leading space.
    trimmed="${trimmed## }"
    # Strip trailing space.
    trimmed="${trimmed%% }"

    echo "$trimmed"
}

例如:

test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"

输出:

'one leading', 'one trailing', 'one leading and one trailing'

去掉所有前导和尾随空格

trim()
{
    local trimmed="$1"

    # Strip leading spaces.
    while [[ $trimmed == ' '* ]]; do
       trimmed="${trimmed## }"
    done
    # Strip trailing spaces.
    while [[ $trimmed == *' ' ]]; do
        trimmed="${trimmed%% }"
    done

    echo "$trimmed"
}

例如:

test4="$(trim "  two leading")"
test5="$(trim "two trailing  ")"
test6="$(trim "  two leading and two trailing  ")"
echo "'$test4', '$test5', '$test6'"

输出:

'two leading', 'two trailing', 'two leading and two trailing'

其他回答

Read已经修整了空白,所以在bash中你可以这样做:

$ read foo <<< "   foo  bar   two spaces follow   "
$ echo ".$foo."
.foo  bar   two spaces follow.

POSIX兼容的版本稍长一些

$ read foo << END
   foo  bar   two spaces follow   
END
$ echo ".$foo."
.foo  bar   two spaces follow.

如果启用了shop -s extglob,那么下面是一个简洁的解决方案。

这招对我很管用:

text="   trim my edges    "

trimmed=$text
trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front
trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back

echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed

#Result
<trim my edges>

用更少的行数来获得相同的结果:

text="    trim my edges    "
trimmed=${${text##+( )}%%+( )}

赋值函数忽略前导和后面的空格,因此可以用于修剪:

$ var=`echo '   hello'`; echo $var
hello

这没有不必要的通配符问题,而且,内部空白是未修改的(假设$IFS被设置为默认值,即' \t\n')。

它一直读取到第一个换行符(但不包括换行符)或字符串的结尾,以先到者为准,并删除任何前导和尾随空格以及\t字符的混合。如果你想保留多行(同时去掉开头和结尾换行符),请使用read -r -d " var << eof;但是请注意,如果您的输入恰好包含\neof,它将在之前被切断。(其他形式的空白,即\r、\f和\v,即使您将它们添加到$IFS,也不会被剥离。)

read -r var << eof
$var
eof

要做到这一点,最简单和最便宜的方法是利用回声忽略空格。所以,就用

dest=$(echo $source)

例如:

> VAR="   Hello    World   "
> echo "x${VAR}x"
x   Hello    World   x
> TRIMD=$(echo $VAR)
> echo "x${TRIMD}x"
xHello Worldx

注意,这也将多个空格合并为一个空格。