Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.

share|improve this question
4  
Why is it so important to avoid sed? Use whatever works! – David Richerby Jul 22 '14 at 23:00
3  
Because I know how to do it with sed. Wanted to know other ways : ) – gkmohit Jul 22 '14 at 23:07
up vote 40 down vote accepted

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.

share|improve this answer
    
This is a great solution too . . . I dont know which one to choose now :/ @Gnouc – gkmohit Jul 22 '14 at 19:11
    
Feel free to chose any solution that you like and it works for you. A note that my solution is different with @polym's answer. – cuonglm Jul 22 '14 at 19:13
1  
:)) yay! @Gnouc s answer is really dynamic, because he uses awk, he can do anything. You can also accept his solution. Just one thing: Gnouc can you possibly explain what the awk format in your command does? Also can you add tabs/spaces so that the output is conforming to Unknown's expected output? – polym Jul 22 '14 at 19:17
1  
@polym: With Unknown's last edit, he seems only want one space, not output like column -t does. Add explaination for awk. – cuonglm Jul 22 '14 at 19:30
1  
There is a small difference here. tr will replace two spaces at the end of a line with a single space. awk will remove all trailing spaces. – Anne van Rossum Sep 24 '15 at 10:40

Just use column:

column -t inputFile

Output:

ID  Name
1   a
2   b
3   g
6   f
share|improve this answer
    
Wonderful and a quick reply :) – gkmohit Jul 22 '14 at 19:04
1  
@Unknown Great to be at service :)! – polym Jul 22 '14 at 19:05
1  
@Gnouc wow cool, column also takes a file as argument. nice thanks! – polym Jul 22 '14 at 19:05
    
How can I get the second column only if I want ? I tried column -t f1.txt | cut -d " " -f2 But was not a solution i expected – gkmohit Jul 22 '14 at 19:08
1  
Use awk then: column -t file | awk '{print $2}' prints the second column only – polym Jul 22 '14 at 19:09

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 %s\n' "$a" "$b"
done < f1.txt
share|improve this answer
1  
In the first place, when compared with tr - this is a terribly weak suggestion efficiency-wise unless the input is just too small too outweigh the tiny cost of tr's invocation - which is not to mention how much more work it takes to write. Last, wouldn't you say that this post does not actually answer the question as asked? What is the best way to replace all the white spaces with one space using only tr? – mikeserv Jul 24 '14 at 23:22
    
And besides - couldn't you more easily just do something with $IFS? Maybe like: IFS=' <tab>' set -f ; echo $(cat <file)? – mikeserv Jul 24 '14 at 23:49

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  "val1\t\tval2   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. Here I am parsing port from Redis config. file:

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

Output:

6379

For more details covering the nuances of whitespace

share|improve this answer
    
To just squeeze, tr is quite reasonable, but when you ALSO want to match a line to a pattern AND select one (horizontal) space delimited field, use awk '/^port/ {print $2}' $redisconf – dave_thompson_085 Jun 15 at 20:39
    
@dave_thompson_85: Yes, the accepted answer already points this out. Awk is the superior tool. But, at the cost of a much higher learning curve. I was trying to answer the question as asked at the OP's perceived level of experience. My power tool, when I choose to wield it is Perl: perl -ane 'print $F[1] if /^port/' – user3183018 Jun 18 at 13:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.