Replace multiple spaces with one using 'tr' only

I have a file, f1.txt:

ID     Name
1      a
2         b
3   g
6            f

The number of spaces is not fixed. What is the best way to replace all the white spaces with one space using only tr?

This is what I have so far:

cat f1.txt | tr -d " "

But the output is:

IDName
1a
2b
3g
6f

But I want it to look like this:

ID Name
1 a
2 b
3 g
6 f

Please try and avoid sed.

Asked By: gkmohit

||

Just use column:

column -t inputFile

Output:

ID  Name
1   a
2   b
3   g
6   f
Answered By: polym

With tr, use the squeeze repeat option:

$ tr -s " " < file
ID Name
1 a
2 b
3 g
6 f

Or you can use an awk solution:

$ awk '{$2=$2};1' file
ID Name
1 a
2 b
3 g
6 f

When you change a field in record, awk rebuild $0, takes all field and concat them together, separated by OFS, which is a space by default.

That will squeeze sequences of space and tabs (and possibly other blank characters depending on the locale and implementation of awk) into one space, but also remove the leading and trailing blanks off each line.

Answered By: cuonglm

Who needs a program (other than the shell)?

while read a b
do
    echo "$a $b"
done < f1.txt

If you want the values in the second column to line up, as in polym’s column answer,
use printf instead of echo:

while read a b
do
    printf '%-2s %sn' "$a" "$b"
done < f1.txt

If you want to squeeze “white space” you will want to use tr’s pre-defined character sets “:blank:” (horizontal whitespace tab and space) or “:space:” (verical whitespace) :

/bin/echo -e  "val1ttval2   val3" | tr -s "[:blank:]"

Examples were run on Red Hat 5 (GNU tr).

In my case I wanted to normalize all whitespace to a single space so I could rely on the space as a delmitter.

As pointed out by dastrobu’s second comment I missed the wording in the man page:

 -s uses the last specified SET, and occurs after translation or deletion.

This allows us to eliminate the first tr. Kudo’s to scott for his patiences in the face of my denseness.

Before, parsing port from Redis config. file:

grep "^port" $redisconf | tr "[:blank:]" " " | tr -s "[:blank:]"  | cut -d" " -f2

After, with SET2 being specified with the squeeze:

grep "^port" $redisconf | tr -s "[:blank:]" " " | cut -d" " -f2

Output:

6379

For more details covering the nuances of whitespace

Demonstrate where squeeze alone fails when successive mixed characters which fall into the [:blank:] character class are involved:

 /usr/bin/printf '%s t %s' id myname | tr -s "[:blank:]"  | od -cb
0000000   i   d      t       m   y   n   a   m   e
        151 144 040 011 040 155 171 156 141 155 145
0000013

Note: My two string fields in the printf format are separated by 1 space, 1 tab, 1 space. After the squeeze this sequence still exists. In the output of the Octal dump this is represented by ascii sequence 040 011 040.

Answered By: user3183018

This is an old question and solved many times. Just for completeness: I had a simillar issue, but wanted to pass lines via pipe to antother program. I used xargs.

-L max-lines
   Use at most max-lines nonblank input lines per command line.
   Trailing blanks cause an input line to be logically continued 
   on the next input line.  Implies -x.

so cat f1.txt | xargs -L1 seems to output exactly what you want.

Answered By: Martin Seitl

The simplest solution of trimming the string of white spaces is to use the xargs command. Example:

[root@localhost ~]# echo "    bla   bla     truc "|xargs
bla bla truc

After that you can easily program the loop using the cut command to get the values and manipulate them. Here is the exact example:

[root@localhost ~]# cat <<EOF>f1.txt
ID     Name
1      a
2         b
3   g
6            f
EOF
[root@localhost ~]# cat testscr.sh

#!/bin/bash
i=0
onelinevars=`cat f1.txt |xargs`
while [[ "$i" -lt `echo $onelinevars|wc -w` ]]; do
  if [[ $((i%2)) -eq 1 ]]; then
    echo -n `echo $onelinevars|cut -d ' ' -f $i`
    echo -n ' '
    echo `echo $onelinevars|cut -d ' ' -f $((i+1))`
  fi
  i=$((i+1))
done
[root@localhost ~]# ./testscr.sh

ID Name
1 a
2 b
3 g
6 f
Answered By: Petar Brcic
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.