如何使用Bash用单个空格替换多个空格?

时间:2018-05-09 18:25:35

标签: string bash shell replace

我想用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内部语法而不是调用外部程序,如果可能的话。

3 个答案:

答案 0 :(得分:9)

以下是使用纯bashextglob

执行此操作的方法
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.

有许多方法可以给猫皮肤。

如果附带的空白可以包含混合spacestabs,那么您可以使用:

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.