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

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

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

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

or

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

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


当前回答

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

dest=$(echo $source)

例如:

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

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

其他回答

你可以简单地使用echo进行修剪:

foo=" qsdqsd qsdqs q qs   "

# Not trimmed
echo \'$foo\'

# Trim
foo=`echo $foo`

# Trimmed
echo \'$foo\'

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

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

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

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

if [ -n "$var" ]; then

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

我将简单地使用sed:

function trim
{
    echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}'
}

a)单行字符串使用示例

string='    wordA wordB  wordC   wordD    '
trimmed=$( trim "$string" )

echo "GIVEN STRING: |$string|"
echo "TRIMMED STRING: |$trimmed|"

输出:

GIVEN STRING: |    wordA wordB  wordC   wordD    |
TRIMMED STRING: |wordA wordB  wordC   wordD|

b)多行字符串使用示例

string='    wordA
   >wordB<
wordC    '
trimmed=$( trim "$string" )

echo -e "GIVEN STRING: |$string|\n"
echo "TRIMMED STRING: |$trimmed|"

输出:

GIVEN STRING: |    wordAA
   >wordB<
wordC    |

TRIMMED STRING: |wordAA
   >wordB<
wordC|

c)最后说明: 如果你不喜欢使用函数,对于单行字符串,你可以简单地使用“更容易记住”的命令,比如:

echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

例子:

echo "   wordA wordB wordC   " | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

输出:

wordA wordB wordC

在多行字符串上使用上述方法也可以,但请注意,它也会切断任何尾随/前导内部多行空间,就像GuruM在评论中注意到的那样

string='    wordAA
    >four spaces before<
 >one space before<    '
echo "$string" | sed -e 's/^[ \t]*//' | sed -e 's/[ \t]*$//'

输出:

wordAA
>four spaces before<
>one space before<

所以如果你介意保留这些空格,请使用我回答开头的函数!

d)解释sed语法“find and replace”在函数trim中使用的多行字符串:

sed -n '
# If the first line, copy the pattern to the hold buffer
1h
# If not the first line, then append the pattern to the hold buffer
1!H
# If the last line then ...
$ {
    # Copy from the hold to the pattern buffer
    g
    # Do the search and replace
    s/^[ \t]*//g
    s/[ \t]*$//g
    # print
    p
}'

虽然它不是严格的Bash,这将做你想要的和更多:

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

如果你也想让它小写,可以这样做:

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

这就是我所做的,结果完美而简单:

the_string="        test"
the_string=`echo $the_string`
echo "$the_string"

输出:

test