如何从Bashvariables修剪空白?

我有这个代码的shell脚本:

var=`hg st -R "$path"` if [ -n "$var" ]; then echo $var fi 

但是条件代码总是执行,因为hg st总是打印至less一个换行符。

  • 有没有一种简单的方法来从$var删除空白(如PHP中的 trim() )?

要么

  • 有没有处理这个问题的标准方式?

我可以使用sed或AWK ,但是我想认为这个问题有一个更优雅的解决scheme。

我们定义一个包含前导,尾随和中间空格的variables:

 FOO=' test test test ' echo -e "FOO='${FOO}'" # > FOO=' test test test ' echo -e "length(FOO)==${#FOO}" # > length(FOO)==16 

如何删除所有的空格(在tr中用[:space:]表示):

 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支持它,你可以replaceecho -e "${FOO}" | sed ... echo -e "${FOO}" | sed ... sed ... <<<${FOO} (尾随空格):

 FOO_NO_TRAIL_SPACE="$(sed -e 's/[[:space:]]*$//' <<<${FOO})" 

一个简单的答案是:

 echo " lol " | xargs 

Xargs会为你做修整。 这是一个命令/程序,没有参数,返回修剪的string,就这么简单!

注意:这不会删除内部空间,所以"foo bar"保持不变。 它不会成为"foobar"

有一种解决scheme只使用Bash内置的通配符

 var=" abc " # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" echo "===$var===" 

这里的function相同:

 trim() { local var="$*" # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" echo -n "$var" } 

您将string以引用的forms进行修剪。 例如:

 trim " abc " 

这个解决scheme的一个好处是,它可以与任何POSIX兼容的shell一起工作。

参考

  • 从Bashvariables ( 原始源 ) 删除前导和尾随空白

Bash有一个称为参数扩展的特性,除此之外,它允许基于所谓模式的stringreplace(模式类似于正则expression式,但是存在基本的差异和限制)。 [flussence的原始行:Bash有正则expression式,但是它们隐藏得很好:]

以下演示如何从一个variables值中删除所有的空白(甚至从内部)。

 $ 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来修剪:

 foo=" qsdqsd qsdqs q qs " # Not trimmed echo \'$foo\' # Trim foo=`echo $foo` # Trimmed echo \'$foo\' 

从Bash指南部分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 

下面是一个包含在函数中的相同function(注意:需要引用传递给函数的inputstring):

 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"; 
 #!/bin/sh trim() { trimmed=$1 trimmed=${trimmed%% } trimmed=${trimmed## } echo "$trimmed" } HELLO_WORLD=$(trim "hello world ") FOO_BAR=$(trim " foo bar") BOTH_SIDES=$(trim " both sides ") echo "'${HELLO_WORLD}', '${FOO_BAR}', '${BOTH_SIDES}'" 

你可以用tr删除换行符:

 var=`hg st -R "$path" | tr -d '\n'` if [ -n $var ]; then echo $var done 

通过启用Bash的扩展模式匹配function( shopt -s extglob ),您可以使用以下命令:

{trimmed##*( )}

去除任意数量的领先空间。

 # 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 

我一直用sed来完成

  var=`hg st -R "$path" | sed -e 's/ *$//'` 

如果有一个更优雅的解决scheme,我希望有人张贴。

为了从string的开头和结尾删除所有的空格(包括行尾字符):

 echo $variable | xargs echo -n 

这也将删除重复的空间:

 echo " this string has a lot of spaces " | xargs echo -n 

产生:“这个string有很多空格”

对不起所有人,在我的脚本的其他地方有一个问题,我认为 var有一个尾随的换行符,但事实并非如此。 命令replace条自动跟随换行符,如下所述: http : //tldp.org/LDP/abs/html/commandsub.html 。

有很多答案,但我仍然相信我刚刚写的脚本是值得提及的,因为:

  • 它已经在shell bash / dash / busybox shell中成功testing过了
  • 它是非常小的
  • 它不依赖于外部命令,也不需要fork( – >快速和低资源使用)
  • 它按预期工作:
    • 它从开始和结束剥离所有空格和制表符,但不是更多
    • 重要的是:它不会从string中间删除任何东西(许多其他答案),甚至换行符也会保留下来
    • 特殊: "$*"使用一个空格连接多个参数。 如果你想修剪&只输出第一个参数,请使用"$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< 

我已经看到脚本只是使用variables赋值来完成这项工作:

 $ xyz=`echo -e 'foo \n bar'` $ echo $xyz foo bar 

空格会自动合并和裁剪。 必须小心shell元字符(潜在的注入风险)。

我还build议在shell条件中始终使用双引号variablesreplace:

 if [ -n "$var" ]; then 

因为variables中的-o或其他内容可以修改你的testing参数。

你可以使用老派tr 。 例如,这将返回git仓库中已修改文件的数量,删除空格。

 MYVAR=`git ls-files -m|wc -l|tr -d ' '` 
 var=' abc ' trimmed=$(echo $var) 

这对我工作:

 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 <trim my edges> 

为了将相同的结果放在较less的行上:

 text=" trim my edges " trimmed=${${text##+( )}%%+( )} 

使用AWK:

 echo $var | awk '{gsub(/^ +| +$/,"")}1' 

这里有一个trim()函数,可以修整和规范空白

 #!/bin/bash function trim { echo $* } echo "'$(trim " one two three ")'" # 'one two three' 

另一个使用正则expression式的变体。

 #!/bin/bash function trim { local trimmed="$@" if [[ "$trimmed" =~ " *([^ ].*[^ ]) *" ]] then trimmed=${BASH_REMATCH[1]} fi echo "$trimmed" } echo "'$(trim " one two three ")'" # 'one two three' 

这并不存在不必要的通配问题,而且内部空白也是未修改的(假设$IFS被设置为默认值,即' \t\n' )。

它可以读取第一个换行符(不包括它)或string的末尾(以先到者为准),并去除前导空格和尾部空格以及\t字符的任意组合。 如果你想保留多行(也可以去掉前导和尾随的换行符),可以使用read -r -d '' var << eof来代替。 但是,请注意,如果您的input恰好包含\neof ,它将在之前被截断。 (即使将它们添加到$ IFS,其他forms的空白,即\r\f\v不会被去除。

 read -r var << eof $var eof 

分配忽略前导和尾随空白,因此可以用于修剪:

 $ var=`echo ' hello'`; echo $var hello 

我会简单地使用sed:

 function trim { echo "$1" | sed -n '1h;1!H;${;g;s/^[ \t]*//g;s/[ \t]*$//g;p;}' } 

a)单行string使用示例

 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的使用示例

 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)最后说明:
如果你不喜欢使用函数,对于单行string,你可以简单地使用一个“更容易记住”的命令,如:

 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 

多行string中使用上面的代码也是可以的 ,但是请注意,它也会削减任何尾随/领先的内部多个空间,就像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< 

所以,如果你不介意保留这些空格,请在我的答案开始处使用该function!

d)函数trim中使用的多行string中的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 }' 
 # Strip leading and trailing white space (new line inclusive). trim(){ [[ "$1" =~ ^[[:space:]]*(.*[^[:space:]])[[:space:]]*$ ]] printf "%s" "${BASH_REMATCH[1]}" } 

要么

 # Strip leading white space (new line inclusive). ltrim(){ [[ "$1" =~ ^[[:space:]]*(.*[^[:space:]]) ]] printf "%s" "${BASH_REMATCH[1]}" } # Strip trailing white space (new line inclusive). rtrim(){ [[ "$1" =~ ^[[:space:]]*(.*[^[:space:]])[[:space:]]*$ ]] printf "%s" "${BASH_REMATCH[1]}" } # 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")" } 

要么

build立在moskit's expr的基础上

 # 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")")" } 
 #!/bin/bash function trim { typeset trimVar eval trimVar="\${$1}" read trimVar << EOTtrim $trimVar EOTtrim eval $1=\$trimVar } # Note that the parameter to the function is the NAME of the variable to trim, # not the variable contents. However, the contents are trimmed. # Example of use: while read aLine do trim aline echo "[${aline}]" done < info.txt # File info.txt contents: # ------------------------------ # ok hello there $ # another line here $ #and yet another $ # only at the front$ #$ # Output: #[ok hello there] #[another line here] #[and yet another] #[only at the front] #[] 

To remove spaces and tabs from left to first word, enter:

 echo " This is a test" | sed "s/^[ \t]*//" 

cyberciti.biz/tips/delete-leading-spaces-from-front-of-each-word.html

This will remove all the whitespaces from your String,

  VAR2="${VAR2//[[:space:]]/}" 

/ replaces the first occurrence and // all occurrences of whitespaces in the string. Ie all white spaces get replaced by – nothing

This trims multiple spaces of the front and end

whatever=${whatever%% *}

whatever=${whatever#* }

This is the simplest method I've seen. It only uses Bash, it's only a few lines, the regexp is simple, and it matches all forms of whitespace:

 if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]] then test=${BASH_REMATCH[1]} fi 

Here is a sample script to test it with:

 test=$(echo -e "\n \t Spaces and tabs and newlines be gone! \t \n ") echo "Let's see if this works:" echo echo "----------" echo -e "Testing:${test} :Tested" # Ugh! echo "----------" echo echo "Ugh! Let's fix that..." if [[ "$test" =~ ^[[:space:]]*([^[:space:]].*[^[:space:]])[[:space:]]*$ ]] then test=${BASH_REMATCH[1]} fi echo echo "----------" echo -e "Testing:${test}:Tested" # "Testing:Spaces and tabs and newlines be gone!" echo "----------" echo echo "Ah, much better." 

I created the following functions. I am not sure how portable printf is, but the beauty of this solution is you can specify exactly what is "white space" by adding more character codes.

  iswhitespace() { n=`printf "%d\n" "'$1'"` if (( $n != "13" )) && (( $n != "10" )) && (( $n != "32" )) && (( $n != "92" )) && (( $n != "110" )) && (( $n != "114" )); then return 0 fi return 1 } trim() { i=0 str="$1" while (( i < ${#1} )) do char=${1:$i:1} iswhitespace "$char" if [ "$?" -eq "0" ]; then str="${str:$i}" i=${#1} fi (( i += 1 )) done i=${#str} while (( i > "0" )) do (( i -= 1 )) char=${str:$i:1} iswhitespace "$char" if [ "$?" -eq "0" ]; then (( i += 1 )) str="${str:0:$i}" i=0 fi done echo "$str" } #Call it like so mystring=`trim "$mystring"`