我有一个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,但我认为有一个更优雅的解决方案来解决这个问题。
当前回答
使用AWK:
echo $var | awk '{gsub(/^ +| +$/,"")}1'
其他回答
这里有一个trim()函数,用于修整和规范化空白
#!/bin/bash
function trim {
echo $*
}
echo "'$(trim " one two three ")'"
# 'one two three'
还有一种使用正则表达式的变体。
#!/bin/bash
function trim {
local trimmed="$@"
if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]]
then
trimmed=${BASH_REMATCH[1]}
fi
echo "$trimmed"
}
echo "'$(trim " one two three ")'"
# 'one two three'
我见过脚本只是使用变量赋值来完成工作:
$ xyz=`echo -e 'foo \n bar'`
$ echo $xyz
foo bar
空格会自动合并和修剪。必须小心shell元字符(潜在的注入风险)。
我还建议在shell条件句中使用双引号变量替换:
if [ -n "$var" ]; then
因为变量中的-o或其他内容可能会修改测试参数。
在BASH中有几个不同的选项:
line=${line##+([[:space:]])} # strip leading whitespace; no quote expansion!
line=${line%%+([[:space:]])} # strip trailing whitespace; no quote expansion!
line=${line//[[:space:]]/} # strip all whitespace
line=${line//[[:space:]]/} # strip all whitespace
line=${line//[[:blank:]]/} # strip all blank space
前两个需要预先设置/启用extglob:
shopt -s extglob # bash only
注意:引号内的变量展开打破了前两个例子!
这里详细介绍了POSIX括号表达式的模式匹配行为。如果您正在使用更现代/可黑客的shell,例如Fish,则有用于字符串修剪的内置函数。
我将简单地使用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
}'
剥离一个前导和一个后导空间
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'