如何用只有bash内置函数的字符串中的单个空格替换多个空格

Bru*_*ica 4 string bash shell replace

我想用bash用一个空格替换字符串中的多个相邻空格.例:

原始字符串:

"too         many       spaces."
Run Code Online (Sandbox Code Playgroud)

转换字符串:

"too many spaces."
Run Code Online (Sandbox Code Playgroud)

我尝试了类似的东西"${str//*( )/.}",awk '{gsub(/[:blank:]/," ")}1'但我无法做到.

注意:我能够使它工作,<CMD_THAT_GENERATES_THE_INPUT_STRINGH> | perl -lpe's/\s+/ /g'但我不得不使用perl来完成这项工作.我想使用一些bash内部语法而不是调用外部程序,如果可能的话.

Jam*_*own 9

使用tr:

$ echo "too         many       spaces." | tr -s ' '
too many spaces
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

编辑:哦,顺便说一下:

$ s="foo      bar"
$ echo $s
foo bar
$ echo "$s"
foo      bar
Run Code Online (Sandbox Code Playgroud)

编辑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
Run Code Online (Sandbox Code Playgroud)

超过7秒?!这怎么可能呢.嗯,这款迷你笔记本电脑是2014年,但仍然.然后再说:

$ time echo "${s//+( )/ }" > /dev/null

real    0m1.198s
user    0m1.192s
sys     0m0.000s
Run Code Online (Sandbox Code Playgroud)

  • 我肯定会在没有bash扩展的POSIX shell上使用这条路线.也就是说,当一个*可以*使用bash时,运行(合理的输入大小)比@anubhava给出的方法慢得多. (3认同)
  • ...等等,找到了——我没有启用 extglob。好吧,这是一个合法的结果。可能会添加“shopt -s extglob”,使其可供尝试复制的人复制和粘贴。 (2认同)

anu*_*ava 9

这里是一个办法做到这一点使用纯bashextglob:

s="too         many       spaces."

shopt -s extglob
echo "${s//+([[:blank:]])/ }"
Run Code Online (Sandbox Code Playgroud)

too many spaces.
Run Code Online (Sandbox Code Playgroud)
  • 括号表达式[[:blank:]]匹配空格或制表符
  • +([[:blank:]])匹配一个或多个括号表达式(要求extglob)


Dav*_*ica 5

使用 BRE 的另一个简单sed表达式是:

sed 's/[ ][ ]*/ /g'
Run Code Online (Sandbox Code Playgroud)

例如:

$ echo "too         many       spaces." | sed 's/[ ][ ]*/ /g'
too many spaces.
Run Code Online (Sandbox Code Playgroud)

给猫剥皮的方法有很多种。

如果封闭的空格spaces可以由混合和组成tabs,那么您可以使用:

sed 's/\s\s*/ /g'
Run Code Online (Sandbox Code Playgroud)

如果你只是想让 bash 分词处理它,只需回显你的字符串而不带引号,例如

$ echo "too         many       spaces." | while read line; do echo $line; done
too many spaces.
Run Code Online (Sandbox Code Playgroud)

继续同样的想法,如果带有空格的字符串已经存储在变量中,您可以简单地echo命令替换中使用不带引号的命令,让 bash 删除您的附加空格,例如

$ foo="too         many       spaces."; bar=$(echo $foo); echo "$bar"
too many spaces.
Run Code Online (Sandbox Code Playgroud)