我有一个包含以下代码的shell脚本:
var=`hg st -R "$path"` if [ -n "$var" ]; then echo $var fi
但条件代码总是执行,因为hg st
始终打印至少一个换行符.
是否有一种简单的方法可以从中删除空格$var
(比如trim()
在PHP中)?
要么
有没有一种标准的方法来处理这个问题?
我可以使用sed或AWK,但我想有一个更优雅的解决方案来解决这个问题.
让我们定义一个包含前导,尾随和中间空格的变量:
FOO=' test test test ' echo -e "FOO='${FOO}'" # > FOO=' test test test ' echo -e "length(FOO)==${#FOO}" # > length(FOO)==16
如何删除所有空格(用[:space:]
in 表示tr
):
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 "length(FOO_NO_WHITESPACE)==${#FOO_NO_WHITESPACE}" # > length(FOO_NO_WHITESPACE)==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 "length(FOO_NO_LEAD_SPACE)==${#FOO_NO_LEAD_SPACE}" # > length(FOO_NO_LEAD_SPACE)==15
如何仅删除尾随空格:
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 "length(FOO_NO_TRAIL_SPACE)==${#FOO_NO_TRAIL_SPACE}" # > length(FOO_NO_TRAIL_SPACE)==15
如何删除前导和尾随空格 - 链接sed
s:
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 "length(FOO_NO_EXTERNAL_SPACE)==${#FOO_NO_EXTERNAL_SPACE}" # > length(FOO_NO_EXTERNAL_SPACE)==14
或者,如果您的bash支持它,您可以替换echo -e "${FOO}" | sed ...
为sed ... <<<${FOO}
,如此(对于尾随空格):
FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})"
一个简单的答案是:
echo " lol " | xargs
Xargs会为你做修剪.它是一个命令/程序,没有参数,返回修剪过的字符串,就这么简单!
注意:这不会删除内部空间,因此"foo bar"
保持不变.它不会成为"foobar"
.
有一个解决方案只使用称为通配符的 Bash内置函数:
var=" abc " # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" echo "===$var==="
这里包含在函数中:
trim() { local var="$*" # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" echo -n "$var" }
您以引用的形式传递要剪裁的字符串.例如:
trim " abc "
这个解决方案的一个好处是它可以与任何符合POSIX的shell一起使用.
从Bash变量中删除前导和尾随空格(原始源)
Bash有一个称为参数扩展的功能,除其他外,它允许基于所谓的模式替换字符串(模式类似于正则表达式,但存在基本的差异和限制).[flussence的原始行:Bash有正则表达式,但它们被隐藏得很好:]
下面演示了如何从变量值中删除所有空白区域(甚至从内部).
$ 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
为了从字符串的开头和结尾删除所有空格(包括行尾字符):
echo $variable | xargs echo -n
这将删除重复的空格:
echo " this string has a lot of spaces " | xargs echo -n
产生:'这个字符串有很多空格'
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 Guide部分关于globbing
在参数扩展中使用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";
如果我们改变要在子shell中执行的函数,我们不必担心检查extglob的当前shell选项,我们可以设置它而不影响当前的shell.这极大地简化了功能.我还"就地"更新位置参数,所以我甚至不需要局部变量
trim() { shopt -s extglob set -- "${1##+([[:space:]])}" printf "%s" "${1%%+([[:space:]])}" }
所以:
$ 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
你可以简单地修剪echo
:
foo=" qsdqsd qsdqs q qs " # Not trimmed echo \'$foo\' # Trim foo=`echo $foo` # Trimmed echo \'$foo\'
使用Bash的扩展模式匹配功能enabled(shopt -s extglob
),您可以使用:
{trimmed##*( )}
删除任意数量的前导空格.
我总是用sed完成它
var=`hg st -R "$path" | sed -e 's/ *$//'`
如果有一个更优雅的解决方案,我希望有人发布它.
您可以删除换行符tr
:
var=`hg st -R "$path" | tr -d '\n'` if [ -n $var ]; then echo $var done
# 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 $'\n\n\t hey\n\t ho \t\n' $'hey\n\t ho' && test_trim $'\n' '' && test_trim '\n' '\n' && echo passed
这对我有用:
text=" trim my edges " trimmed=$text trimmed=${trimmed##+( )} #Remove longest matching series of spaces from the front trimmed=${trimmed%%+( )} #Remove longest matching series of spaces from the back echo "<$trimmed>" #Adding angle braces just to make it easier to confirm that all spaces are removed #Result
为了相同的结果,将它放在更少的行上:
text=" trim my edges " trimmed=${${text##+( )}%%+( )}
有很多答案,但我仍然相信我刚写的脚本值得一提,因为:
它在shell bash/dash/busybox shell中成功测试过
它非常小
它不依赖于外部命令,也不需要fork( - >快速和低资源使用)
它按预期工作:
它从开始和结束中删除所有空格和制表符,但不是更多
重要的是:它不会从字符串的中间删除任何东西(许多其他答案都可以),甚至换行也会保留
special:"$*"
使用一个空格连接多个参数.如果要仅修剪和输出第一个参数,请"$1"
改用
如果匹配文件名模式等没有任何问题
剧本:
trim() { local s2 s="$*" # note: the brackets in each of the following two lines contain one space # and one tab until s2="${s#[ ]}"; [ "$s2" = "$s" ]; do s="$s2"; done until s2="${s%[ ]}"; [ "$s2" = "$s" ]; do s="$s2"; done echo "$s" }
用法:
mystring=" here is something " mystring=$(trim "$mystring") echo ">$mystring<"
输出:
>here is something<
你可以使用老派tr
.例如,这将返回git存储库中已修改文件的数量,并删除空白.
MYVAR=`git ls-files -m|wc -l|tr -d ' '`
# Strip leading and trailing white space (new line inclusive). trim(){ [[ "$1" =~ [^[:space:]](.*[^[:space:]])? ]] printf "%s" "$BASH_REMATCH" }
要么
# Strip leading white space (new line inclusive). ltrim(){ [[ "$1" =~ [^[:space:]].* ]] printf "%s" "$BASH_REMATCH" } # Strip trailing white space (new line inclusive). rtrim(){ [[ "$1" =~ .*[^[:space:]] ]] printf "%s" "$BASH_REMATCH" } # Strip leading and trailing white space (new line inclusive). trim(){ printf "%s" "$(rtrim "$(ltrim "$1")")" }
要么
# Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a') trim(){ if [ "$2" ]; then trim_chrs="$2" else trim_chrs="[:space:]" fi [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]] printf "%s" "${BASH_REMATCH[1]}" }
要么
# Strip leading specified characters. ex: str=$(ltrim "$str" $'\n a') ltrim(){ if [ "$2" ]; then trim_chrs="$2" else trim_chrs="[:space:]" fi [[ "$1" =~ ^["$trim_chrs"]*(.*[^"$trim_chrs"]) ]] printf "%s" "${BASH_REMATCH[1]}" } # Strip trailing specified characters. ex: str=$(rtrim "$str" $'\n a') rtrim(){ if [ "$2" ]; then trim_chrs="$2" else trim_chrs="[:space:]" fi [[ "$1" =~ ^(.*[^"$trim_chrs"])["$trim_chrs"]*$ ]] printf "%s" "${BASH_REMATCH[1]}" } # Strip leading and trailing specified characters. ex: str=$(trim "$str" $'\n a') trim(){ printf "%s" "$(rtrim "$(ltrim "$1" "$2")" "$2")" }
要么
建立在moskit的expr soulution上......
# Strip leading and trailing white space (new line inclusive). trim(){ printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)[[:space:]]*$"`" }
要么
# Strip leading white space (new line inclusive). ltrim(){ printf "%s" "`expr "$1" : "^[[:space:]]*\(.*[^[:space:]]\)"`" } # Strip trailing white space (new line inclusive). rtrim(){ printf "%s" "`expr "$1" : "^\(.*[^[:space:]]\)[[:space:]]*$"`" } # Strip leading and trailing white space (new line inclusive). trim(){ printf "%s" "$(rtrim "$(ltrim "$1")")" }
我见过脚本只是使用变量赋值来完成这项工作:
$ xyz=`echo -e 'foo \n bar'` $ echo $xyz foo bar
空白会自动合并和修剪.必须注意shell元字符(潜在的注入风险).
我还建议在shell条件中始终双引变量替换:
if [ -n "$var" ]; then
因为变量中的-o或其他内容可能会修改您的测试参数.
我只想使用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)在函数trim中使用的多行字符串上的sed语法"find and replace"的说明:
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 }'
var=' a b c ' trimmed=$(echo $var)
使用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'
赋值忽略前导和尾随空格,因此可用于修剪:
$ var=`echo ' hello'`; echo $var hello
这不会出现不必要的浮点问题,而且内部空白未修改(假设$IFS
设置为默认值' \t\n'
)。
它读取直到第一个换行符(并且不包括它)或字符串的末尾(以先到者为准),并去除前导和尾随空格和\t
字符的任何混合。如果要保留多行(并去除开头和结尾的换行符),请read -r -d '' var << eof
改用;但是请注意,如果您输入的内容恰好包含\neof
,它将在之前被截断。(即使将其他形式的空白,即\r
,\f
和\v
,也不会删除,即使将它们添加到$ IFS中也是如此。)
read -r var << eof $var eof
要从左至第一个单词删除空格和制表符,请输入:
echo " This is a test" | sed "s/^[ \t]*//"
cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html
这将从字符串中删除所有空格,
VAR2="${VAR2//[[:space:]]/}"
/
替换//
字符串中第一次出现的空格和所有出现的空格。即所有空白都被替换为–什么都没有