string - 从bash变量 如何剪裁空白?

  显示原文与译文双语对照的内容

我有一个带有以下代码的shell脚本:


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

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

  • 是否有一个简单的方法来去除 $var ( 像 trim() 中的) 中的空白?

或者

  • 是否有处理这个问题的标准方法?

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

时间:

让我们定义一个包含前导whitespace尾随和中间空白的变量:


FOO=' test test test '
echo -e"FOO='${FOO}'"
#> FOO=' test test test '
echo -e"1+length(FOO)==$(echo -e"${FOO}" | wc -m)"
#> 1+length(FOO)==17

有人可能会争辩 length(FOO) =16,但是 wc 也计算变量的终止换行符。


如何删除所有空白( 由 [[:space:]] 表示):


FOO=' test test test '
FOO_NO_WHITESPACE="$(echo -e"${FOO}" | tr -d '[[:space:]]')"
echo -e"FOO_NO_WHITESPACE='${FOO_NO_WHITESPACE}'"
#> FOO_NO_WHITESPACE='testtesttest'
echo -e"1+length(FOO_NO_WHITESPACE)==$(echo -e"${FOO_NO_WHITESPACE}" | wc -m)"
#> 1+length(FOO_NO_WHITESPACE)==13

同样,wc 计算变量的终止换行符。。 但如果你不指定。 例如,


echo -e"${FOO}" | tr -d '[[:space:]]' | wc -m
#> 12


如何只删除前导空白:


FOO=' test test test '
FOO_NO_LEAD_SPACE="$(echo -e"${FOO}" | sed -e 's/^[[:space:]]*//')"
echo -e"FOO_NO_LEAD_SPACE='${FOO_NO_LEAD_SPACE}'"
#> FOO_NO_LEAD_SPACE='test test test '
echo -e"1+length(FOO_NO_LEAD_SPACE)==$(echo -e"${FOO_NO_LEAD_SPACE}" | wc -m)"
#> 1+length(FOO_NO_LEAD_SPACE)==16


如何只删除尾随空格:


FOO=' test test test '
FOO_NO_TRAIL_SPACE="$(echo -e"${FOO}" | sed -e 's/[[:space:]]*$//')"
echo -e"FOO_NO_TRAIL_SPACE='${FOO_NO_TRAIL_SPACE}'"
#> FOO_NO_TRAIL_SPACE=' test test test'
echo -e"1+length(FOO_NO_TRAIL_SPACE)==$(echo -e"${FOO_NO_TRAIL_SPACE}" | wc -m)"
#> 1+length(FOO_NO_TRAIL_SPACE)==16


如何删除前导数字和尾随在 sed s: spaces--chain


FOO=' test test test '
FOO_NO_EXTERNAL_SPACE="$(echo -e"${FOO}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
echo -e"FOO_NO_EXTERNAL_SPACE='${FOO_NO_EXTERNAL_SPACE}'"
#> FOO_NO_EXTERNAL_SPACE='test test test'
echo -e"1+length(FOO_NO_EXTERNAL_SPACE)==$(echo -e"${FOO_NO_EXTERNAL_SPACE}" | wc -m)"
#> 1+length(FOO_NO_EXTERNAL_SPACE)==15

旧问题,但我没有找到一个简单的答案,所以试试:


echo" lol" | xargs

Xargs会为你做修整,它是一个命令/程序,没有参数,返回修剪过的字符串,就像这样 !

注意:这不会删除内部空间,因此 "foo bar" 保持不变,不会变成 "foobar"

"从Bash变量中删除前导&尾随空白",http://codesnippets.joyent.com/posts/show/1816


var=" abc"
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
echo"===$var==="

以下是函数中的包装:


trim() {
 local var="$*"
 var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
 var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
 echo -n"$var"
}

你传递要以引号形式修剪的字符串。 比如:


trim" abc";

所谓上图案 Bash有一个特性称为参数扩展,其中,除此之外,允许字符串替换 based. [ flussence行原始:Bash有 正规表达式,但它们是 well-hidden: ]

指向一个变量value,下面演示如何移除 所有空白域


$ var='abc def'
$ echo"$var"
abc def
# Note: flussence's original expression was"${var//}", which only replaced the *first* space char., wherever it appeared.
$ echo -n"${var//[[:space:]]/}"
abcdef


#!/bin/sh

trim()
{
 trimmed=$1
 trimmed=${trimmed%% }
 trimmed=${trimmed## }

 echo"$trimmed"
}


HELLO_WORLD=$(trim"hello world")
FOO_BAR=$(trim" foo bar")
BOTH_SIDES=$(trim" both sides")
echo"'${HELLO_WORLD}', '${FOO_BAR}', '${BOTH_SIDES}'"

( 注意:刚刚创建了一个帐户,没有足够的声誉来评论,因此一个新的答案)

回应insyte的凯恩回答和的评论:

通过扩展bash模式匹配特性的扩展,你可以使用:

{trimmed##*( )}

删除任意数量的前导空格。

来自组合的Bash指南部分

在参数扩展中使用 extglob


 #Turn on extended globbing 
shopt -s extglob 
 #Trim leading and trailing whitespace from a variable 
x=${x##+([[:space:]])}; x=${x%%+([[:space:]])} 
 #Turn off extended globbing 
shopt -u extglob 

以下是函数中封装的功能( 注意: 需要引用传递给函数的输入字符串:


trim() {
 # Determine if 'extglob' is currently on.
 local extglobWasOff=1
 shopt extglob>/dev/null && extglobWasOff=0 
 (( extglobWasOff )) && shopt -s extglob # Turn 'extglob' on, if currently turned off.
 # Trim leading and trailing whitespace
 local var=$1
 var=${var##+([[:space:]])}
 var=${var%%+([[:space:]])}
 (( extglobWasOff )) && shopt -u extglob # If 'extglob' was off before, turn it back off.
 echo -n"$var" # Output trimmed string.
}

使用方法:


string=" abc def ghi";
#need to quote input-string to preserve internal white-space if any
trimmed=$(trim"$string"); 
echo"$trimmed";


# Trim whitespace from both ends of specified parameter

trim () {
 read -rd '' $1 <<<"${!1}"
}

# Unit test for trim()

test_trim () {
 local foo="$1"
 trim foo
 test"$foo" ="$2"
}

test_trim hey hey &&
test_trim ' hey' hey &&
test_trim 'ho ' ho &&
test_trim 'hey ho' 'hey ho' &&
test_trim ' hey ho ' 'hey ho' &&
test_trim $'nnt heynt ho tn' $'heynt ho' &&
test_trim $'n' '' &&
test_trim 'n' 'n' &&
echo passed

...