How to replace multiple spaces by one tab

28

10

I have some text files which contain some columns separated by a various number of spaces, but instead I need one single tab as a separator. Is it possible to do in Bash?

user_unknown

Posted 2011-02-02T22:26:09.303

Reputation: 325

Thanks for the great input, but i have some single spaces inside a column, so i have to avoid tabbing a single space. sorry for that ,isinformation. – user_unknown – 2011-02-02T22:49:33.367

Answers

33

To convert sequences of more than one space to a tab, but leave individual spaces alone:

sed 's/ \+ /\t/g' inputfile > outputfile

To do this for a number of files:

for inputfile in *
do
    sed 's/ \+ /\t/g' "$inputfile" > tmpfile && mv tmpfile "$inputfile"
done

or

for inputfile in *
do
    sed -i.bak 's/ \+ /\t/g' "$inputfile"
done

or

find . -type f -exec sed -i.bak 's/ \+ /\t/g' {} \;

Paused until further notice.

Posted 2011-02-02T22:26:09.303

Reputation: 86 075

sed: -e expression #1, char 1: unknown command: \.'` – Aaron Franke – 2019-02-10T00:40:36.753

@AaronFranke: What command did you try? None of the examples in my answer should produce that error. – Paused until further notice. – 2019-02-10T01:25:23.800

Sorry, I should've clarified. The find one on the bottom. – Aaron Franke – 2019-02-10T09:06:16.087

@AaronFranke: GNU sed doesn't like to have a space before the backup extension. I've edited my answer. Thanks for the report. – Paused until further notice. – 2019-02-10T13:22:29.853

7

If your character is multiple tabs you can also use tr -s:

-s, --squeeze-repeats   replace each input sequence of a repeated character
                        that is listed in SET1 with a single occurrence

For example:

my_file.txt | tr -s " "

All white spaces will become one.

user597119

Posted 2011-02-02T22:26:09.303

Reputation: 71

This is not what OP is asking for. – RonJohn – 2019-07-21T06:09:07.690

5

You can use sed to replace a number of spaces with a tab.:

Example to replace one-or-more-spaces with one tab:

cat spaced-file | sed 's/ \+/\t/g' > tabbed-file

IvanGoneKrazy

Posted 2011-02-02T22:26:09.303

Reputation: 241

Most useful answer here. – Luís de Sousa – 2016-01-15T14:07:13.390

The OP said the number of spaces was variable, so I don't think this solution will work. – Mikel – 2011-02-02T22:35:31.207

@Mikel. Oops. Thanks for pointing that out. I've edit the post to allow matching for variable spaces. – IvanGoneKrazy – 2011-02-02T22:45:38.873

3

The easiest answer using only bash is:

while read -r col1 col2 col3 ...; do
    echo -e "$col1\t$col2\t$col3..."
done <file

If there are a variable number of columns, you can do this, but it will only work in bash, not sh:

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <file

e.g.

while read -r -a cols; do
    (
        IFS=$'\t'
        echo "${cols[*]}"
    )
done <<EOF
a b   c
d   e    f
  g h i
EOF

produces:

a   b   c
d   e   f
g   h   i

(there is a tab in between each, but it's hard to see when I paste it here)

You could also do it using sed or tr, but notice that the handling of blanks at the start produces different results.

sed:

$ sed 's/  */\t/g' << EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i

tr:

$ tr -s ' ' '\t' <<EOF
a b   c
d   e    f
  g h i
EOF
a       b       c
d       e       f
        g       h       i

Mikel

Posted 2011-02-02T22:26:09.303

Reputation: 7 890

2

perl -p -i -e 's/\s+/\t/g' *.txt

RedGrittyBrick

Posted 2011-02-02T22:26:09.303

Reputation: 70 632

2

Try the following SED script:

 sed 's/  */<TAB>/g' <spaces-file > tabs-file

Where <TAB> is pressing the TAB key.

mdpc

Posted 2011-02-02T22:26:09.303

Reputation: 4 176

0

This is a very simple solution:

    sed -E 's/\s+/\t/g' your_file > new_file

sed basically works in this manner (sed 's/old_pattern/new_pattern/g'). In this case the old pattern is "\s+" which means find space "s" one or more time "+" and the back slash "\" to interpret that as regular expression.
The new pattern is tab "\t" which is written in regular expression format and the "g" is apply the replacement to all lines "globally".

Waleed Omer

Posted 2011-02-02T22:26:09.303

Reputation: 11

1Hello and welcome to superuser. You should take the time to explain your solution. For someone not familiar with *nix systems, sed and regular expressions, this looks like a pile of weird characters. – Mogget – 2016-04-03T21:43:56.407