我想用bash用一个空格替换字符串中的多个相邻空格。例如:
原始字符串:
"too many spaces."
转换字符串:
"too many spaces."
我已尝试"${str//*( )/.}"
或awk '{gsub(/[:blank:]/," ")}1'
之类的内容,但我无法做到正确。
注意:我能够使用<CMD_THAT_GENERATES_THE_INPUT_STRINGH> | perl -lpe's/\s+/ /g'
,但我不得不使用perl来完成这项工作。我想使用一些bash内部语法而不是调用外部程序,如果可能的话。
答案 0 :(得分:9)
以下是使用纯bash
和extglob
:
s="too many spaces."
shopt -s extglob
echo "${s//+([[:blank:]])/ }"
too many spaces.
[[:blank:]]
与空格或制表符匹配+([[:blank:]])
匹配一个或多个括号表达式(需要extglob
)答案 1 :(得分:6)
使用tr
:
$ echo "too many spaces." | tr -s ' '
too many spaces
man tr
:
-s, --squeeze-repeats
replace each sequence of a repeated character that is listed in
the last specified SET, with a single occurrence of that charac‐
ter
编辑:哦,顺便说一下:
$ s="foo bar"
$ echo $s
foo bar
$ echo "$s"
foo bar
编辑2 :关于效果:
$ shopt -s extglob
$ s=$(for i in {1..100} ; do echo -n "word " ; done) # 100 times: word word word...
$ time echo "${s//+([[:blank:]])/ }" > /dev/null
real 0m7.296s
user 0m7.292s
sys 0m0.000s
$ time echo "$s" | tr -s ' ' >/dev/null
real 0m0.002s
user 0m0.000s
sys 0m0.000s
超过7秒?!这怎么可能呢。嗯,这款迷你笔记本电脑是2014年,但仍然。然后再说:
$ time echo "${s//+( )/ }" > /dev/null
real 0m1.198s
user 0m1.192s
sys 0m0.000s
答案 2 :(得分:1)
使用BRE的另一个简单sed
表达式是:
sed 's/[ ][ ]*/ /g'
例如:
$ echo "too many spaces." | sed 's/[ ][ ]*/ /g'
too many spaces.
有许多方法可以给猫皮肤。
如果附带的空白可以包含混合spaces
和tabs
,那么您可以使用:
sed 's/\s\s*/ /g'
如果您只是想让bash分词处理它,只需回显您的字符串,例如。
$ echo "too many spaces." | while read line; do echo $line; done
too many spaces.
继续同样的想法,如果你的带有空格的字符串已经存储在一个变量中,你只需在命令替换中使用echo
不加引号就可以为你的bash删除额外的空格,例如
$ foo="too many spaces."; bar=$(echo $foo); echo "$bar"
too many spaces.