我有一个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,但我认为有一个更优雅的解决方案来解决这个问题。
当前回答
您可以使用老式的tr。例如,它返回git存储库中已修改文件的数量,删除空白。
MYVAR=`git ls-files -m|wc -l|tr -d ' '`
其他回答
这修整了前端和末端的多个空间
whatever=${whatever%% *}
无论= ${无论# *}
剥离一个前导和一个后导空间
trim()
{
local trimmed="$1"
# Strip leading space.
trimmed="${trimmed## }"
# Strip trailing space.
trimmed="${trimmed%% }"
echo "$trimmed"
}
例如:
test1="$(trim " one leading")"
test2="$(trim "one trailing ")"
test3="$(trim " one leading and one trailing ")"
echo "'$test1', '$test2', '$test3'"
输出:
'one leading', 'one trailing', 'one leading and one trailing'
去掉所有前导和尾随空格
trim()
{
local trimmed="$1"
# Strip leading spaces.
while [[ $trimmed == ' '* ]]; do
trimmed="${trimmed## }"
done
# Strip trailing spaces.
while [[ $trimmed == *' ' ]]; do
trimmed="${trimmed%% }"
done
echo "$trimmed"
}
例如:
test4="$(trim " two leading")"
test5="$(trim "two trailing ")"
test6="$(trim " two leading and two trailing ")"
echo "'$test4', '$test5', '$test6'"
输出:
'two leading', 'two trailing', 'two leading and two trailing'
从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
还有一个单元测试的解决方案,它从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+"$@"}
}
"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 $?
}