我有一个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,但我认为有一个更优雅的解决方案来解决这个问题。
当前回答
还有一个单元测试的解决方案,它从stdin中删除$IFS,并适用于任何输入分隔符(甚至$'\0'):
ltrim()
{
# Left-trim $IFS from stdin as a single line
# $1: Line separator (default NUL)
local trimmed
while IFS= read -r -d "${1-}" -u 9
do
if [ -n "${trimmed+defined}" ]
then
printf %s "$REPLY"
else
printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
fi
printf "${1-\x00}"
trimmed=true
done 9<&0
if [[ $REPLY ]]
then
# No delimiter at last line
if [ -n "${trimmed+defined}" ]
then
printf %s "$REPLY"
else
printf %s "${REPLY#"${REPLY%%[!$IFS]*}"}"
fi
fi
}
rtrim()
{
# Right-trim $IFS from stdin as a single line
# $1: Line separator (default NUL)
local previous last
while IFS= read -r -d "${1-}" -u 9
do
if [ -n "${previous+defined}" ]
then
printf %s "$previous"
printf "${1-\x00}"
fi
previous="$REPLY"
done 9<&0
if [[ $REPLY ]]
then
# No delimiter at last line
last="$REPLY"
printf %s "$previous"
if [ -n "${previous+defined}" ]
then
printf "${1-\x00}"
fi
else
last="$previous"
fi
right_whitespace="${last##*[!$IFS]}"
printf %s "${last%$right_whitespace}"
}
trim()
{
# Trim $IFS from individual lines
# $1: Line separator (default NUL)
ltrim ${1+"$@"} | rtrim ${1+"$@"}
}
其他回答
当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
这修整了前端和末端的多个空间
whatever=${whatever%% *}
无论= ${无论# *}
答案有很多,但我仍然认为我刚刚写的剧本值得一提,因为:
it was successfully tested in the shells bash/dash/busybox shell it is extremely small it doesn't depend on external commands and doesn't need to fork (->fast and low resource usage) it works as expected: it strips all spaces and tabs from beginning and end, but not more important: it doesn't remove anything from the middle of the string (many other answers do), even newlines will remain special: the "$*" joins multiple arguments using one space. if you want to trim & output only the first argument, use "$1" instead if doesn't have any problems with matching file name patterns etc
脚本:
trim() {
local s2 s="$*"
until s2="${s#[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
until s2="${s%[[:space:]]}"; [ "$s2" = "$s" ]; do s="$s2"; done
echo "$s"
}
用法:
mystring=" here is
something "
mystring=$(trim "$mystring")
echo ">$mystring<"
输出:
>here is
something<
赋值函数忽略前导和后面的空格,因此可以用于修剪:
$ var=`echo ' hello'`; echo $var
hello
有一个解决方案只使用Bash内置的通配符:
var=" abc "
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "===$var==="
下面是同样的包装在一个函数中:
trim() {
local var="$*"
# remove leading whitespace characters
var="${var#"${var%%[![:space:]]*}"}"
# remove trailing whitespace characters
var="${var%"${var##*[![:space:]]}"}"
printf '%s' "$var"
}
你传递要以引号形式修剪的字符串,例如:
trim " abc "
这个解决方案的一个优点是它可以与任何posix兼容的shell一起工作。
参考
从Bash变量中删除前导和尾随空格(原始源代码)