我有一个shell脚本与这段代码:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
但是条件代码总是执行,因为hg st总是打印至少一个换行符。
是否有一个简单的方法从$var中剥离空白(如PHP中的trim())?
or
有没有处理这个问题的标准方法?
我可以使用sed或AWK,但我认为有一个更优雅的解决方案来解决这个问题。
我有一个shell脚本与这段代码:
var=`hg st -R "$path"`
if [ -n "$var" ]; then
echo $var
fi
但是条件代码总是执行,因为hg st总是打印至少一个换行符。
是否有一个简单的方法从$var中剥离空白(如PHP中的trim())?
or
有没有处理这个问题的标准方法?
我可以使用sed或AWK,但我认为有一个更优雅的解决方案来解决这个问题。
当前回答
当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
其他回答
使用AWK:
echo $var | awk '{gsub(/^ +| +$/,"")}1'
我见过脚本只是使用变量赋值来完成工作:
$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar
空格会自动合并和修剪。必须小心shell元字符(潜在的注入风险)。
我还建议在shell条件句中使用双引号变量替换:
if [ -n "$var" ]; then
因为变量中的-o或其他内容可能会修改测试参数。
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
要做到这一点,最简单和最便宜的方法是利用回声忽略空格。所以,就用
dest=$(echo $source)
例如:
> VAR=" Hello World "
> echo "x${VAR}x"
x Hello World x
> TRIMD=$(echo $VAR)
> echo "x${TRIMD}x"
xHello Worldx
注意,这也将多个空格合并为一个空格。
从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";
如果我们将函数更改为在subshell中执行,我们不必担心检查extglob的当前shell选项,我们可以只设置它而不影响当前shell。这极大地简化了函数。我还更新了位置参数“就地”,所以我甚至不需要一个局部变量
trim() {
shopt -s extglob
set -- "${1##+([[:space:]])}"
printf "%s" "${1%%+([[:space:]])}"
}
so:
$ s=$'\t\n \r\tfoo '
$ shopt -u extglob
$ shopt extglob
extglob off
$ printf ">%q<\n" "$s" "$(trim "$s")"
>$'\t\n \r\tfoo '<
>foo<
$ shopt extglob
extglob off