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

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

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

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

or

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

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


当前回答

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

其他回答

var="  a b  "
echo "$(set -f; echo $var)"

>a b

这里有一个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'

我见过脚本只是使用变量赋值来完成工作:

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

空格会自动合并和修剪。必须小心shell元字符(潜在的注入风险)。

我还建议在shell条件句中使用双引号变量替换:

if [ -n "$var" ]; then

因为变量中的-o或其他内容可能会修改测试参数。

"trim"函数删除所有水平空白:

ltrim () {
    if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/^\h+//g'
    return $?
}

rtrim () {
    if [[ $# -eq 0 ]]; then cat; else printf -- '%s\n' "$@"; fi | perl -pe 's/\h+$//g'
    return $?
}

trim () {
    ltrim "$@" | rtrim
    return $?
}

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.