Americas

  • United States
sandra_henrystocker
Unix Dweeb

Turn tabs into spaces on Linux and vice versa

How-To
Feb 03, 20226 mins
Linux

The Linux expand and unexpand commands can turn tabs into spaces and spaces into tabs, and the sed and awk commands can help.

hp spectre x360 14 1q881av keyboard.jpg
Credit: Ben Patterson/IDG

The Linux expand and unexpand commands sound like they can make files larger and smaller, but what they actually do is turn tabs into spaces and spaces into tabs.

In this post, we’ll use some simple text files to demonstrate what happens when you use expand and unexpand. We’ll also compare how these commands work with some likely more familiar commands—sed and awk—that can provide similar results and offer additional options.

To begin, let’s take a look at this very simple text file:

$ cat Hello
Hello   World
This    is      me!
And     I       am looking      at you!

The output of the od -bc command can be used to verify that the white spaces in this file are provided by tabs (octal value = 011 and the character displayed as “t”) rather than sequences of space characters.

$ od -bc Hello
0000000 110 145 154 154 157 011 127 157 162 154 144 012 124 150 151 163
          H   e   l   l   o  t   W   o   r   l   d  n   T   h   i   s
0000020 011 151 163 011 155 145 041 012 101 156 144 011 111 011 141 155
         t   i   s  t   m   e   !  n   A   n   d  t   I  t   a   m
0000040 040 154 157 157 153 151 156 147 011 141 164 040 171 157 165 041
              l   o   o   k   i   n   g  t   a   t       y   o   u   !
0000060 012
         n

If you use the expand command on a file like this, you’ll see something like this:

$ expand Hello
Hello   World
This    is      me!
And     I       am looking      at you!

Notice that this output looks exactly the same as the original file. Why? Because, without additional arguments, the expand command replaces each tab not with a single space character, but with the number of spaces required to make the output look just like the original file. It also writes its output to standard out. To save the output generated by the command shown above, we could do this:

$ expand Hello > hello

When we look at these two files, they appear to be the same:

$ cat Hello
Hello   World
This    is      me!
And     I       am looking      at you!
$ cat hello
Hello   World
This    is      me!
And     I       am looking      at you!

When we list the files, however, we see that the new file has 25 more characters than the original.

$ ls -l Hello hello
-rw-r—r—. 1 shs shs 74 Feb  2 08:35 hello
-rw-r—r—. 1 shs shs 49 Feb  2 08:28 Hello

If you use the od -bc command on the new file, you should notice that the extra characters are long sequences of blanks.

$ od -bc hello
0000000 110 145 154 154 157 040 040 040 127 157 162 154 144 012 124 150
          H   e   l   l   o               W   o   r   l   d  n   T   h
0000020 151 163 040 040 040 040 151 163 040 040 040 040 040 040 155 145
          i   s                   i   s                           m   e
0000040 041 012 101 156 144 040 040 040 040 040 111 040 040 040 040 040
          !  n   A   n   d                       I
0000060 040 040 141 155 040 154 157 157 153 151 156 147 040 040 040 040
                  a   m       l   o   o   k   i   n   g
0000100 040 040 141 164 040 171 157 165 041 012
                  a   t       y   o   u   !  n

Just remember that, by default, the expanded output is sent to standard out. It doesn’t overwrite the original file unless you redirect the output to another file.

Limiting the number of space characters

If you use the -t option with the expand command, you can limit the number of spaces used to replace each tab. In this example below, we select to replace each tab with a single space.

$ expand -t 1 Hello > hello
$ ls -l Hello hello
-rw-r—r—. 1 shs shs 49 Feb  2 09:02 hello
-rw-r—r—. 1 shs shs 49 Feb  2 08:28 Hello

Notice that the new file now has the same number of characters as the original, but spaces in place of the tabs.

$ od -bc hello
0000000 110 145 154 154 157 040 127 157 162 154 144 012 124 150 151 163
          H   e   l   l   o       W   o   r   l   d  n   T   h   i   s
0000020 040 151 163 040 155 145 041 012 101 156 144 040 111 040 141 155
              i   s       m   e   !  n   A   n   d       I       a   m
0000040 040 154 157 157 153 151 156 147 040 141 164 040 171 157 165 041
              l   o   o   k   i   n   g       a   t       y   o   u   !
0000060 012
         n

If you use -t 2 instead of -t 1, the file looks different and has a couple of additional characters:

$ expand -t 2 Hello > hello2
$ cat hello2
Hello World
This  is  me!
And I am looking  at you!
$ ls -l [Hh]ello*
-rw-r—r—. 1 shs shs    49 Feb  2 09:02 hello
-rw-r—r—. 1 shs shs    49 Feb  2 08:28 Hello
-rw-r—r—. 1 shs shs    52 Feb  2 09:06 hello2

Using -t 4, the file looks noticeably different as up to four blanks are used to replace each tab:

$ expand -t 4 Hello
Hello   World
This    is  me!
And I   am looking  at you!

unexpand

The unexpand command is intended to do the reverse—change spaces into tabs. Say we are starting with the file shown below:

$ cat hello_again
Hello   World!
$ od -bc hello_again
0000000 110 145 154 154 157 040 040 040 127 157 162 154 144 041 012
          H   e   l   l   o               W   o   r   l   d   !  n

Next, we use the unexpand command to turn the string of blanks into a tab:

$ unexpand -a hello_again | od -bc
0000000 110 145 154 154 157 011 127 157 162 154 144 041 012
          H   e   l   l   o  t   W   o   r   l   d   !  n

To save the results, we still need to redirect the output like this:

$ unexpand -a hello_again > hello2

Using sed

sed can turn all tabs in a file into single blanks. Here’s the file along with the sed command:

$ cat Hello
Hello   World
This    is      me!
And     I       am looking      at you!
$ sed ‘s/t/ /g’ Hello
Hello World
This is me!
And I am looking at you!

The “s” inside the single quotes means “substitute”, the t represents a tab and the “g” before the right single-quote means “change all of them”. As with the expand command, you have to redirect the output to another file if you want to use it.

$ sed ‘s/t/ /g’ Hello > hello

Unlike expand, sed changes one tab to one space.

The sed command can also turn space characters into tabs. You just need to reverse the tab and space inside the single quotes like this:

$ sed ‘s/ /t/g’ hello > Hello

Using awk

Another option is to use an awk command like the one shown below (where “OFS” is the output field separator) to turn tabs into single blanks:

$ cat Hello | awk ‘$1=$1’ OFS=’ ‘
Hello World
This is me!
And I am looking at you!

If you also want the first word in each line of a file to be followed by a colon to separate it from the rest of the text, use a command like this:

$ cat days_of_week | awk ‘$1=$1”:”‘ OFS=’ ‘
Sunday: relax and enjoy a day of peace
Monday: plan the week
Tuesday: take trash to the transfer station
Wednesday: do some writing
Thursday: clean the cat box
Friday: do laundry
Saturday: shop

It will use single spaces as separators, replacing any tabs, and will add a “:” at the end of the first string in each line.

To turn blanks into tabs, use t as the output separator:

$ cat days_of_week | awk ‘$1=$1’ OFS=’t’
Sunday  relax   and     enjoy   a       day     of      peace
Monday  plan    the     week
Tuesday take    trash   to      the     transfer        station
Wednesday       do      some    writing
Thursday        clean   the     cat     box
Friday  do      laundry
Saturday        shop

As with the other commands, you need to redirect the output to a new file to preserve it.

cat days_of_week | awk ‘$1=$1”:”‘ OFS=’ ‘ > daily_tasks

Wrap-Up

The expand and unexpand commands have some very specific uses, but other commands like sed and awk provide a lot of flexibility and can help when you want some different options.

sandra_henrystocker
Unix Dweeb

Sandra Henry-Stocker has been administering Unix systems for more than 30 years. She describes herself as "USL" (Unix as a second language) but remembers enough English to write books and buy groceries. She lives in the mountains in Virginia where, when not working with or writing about Unix, she's chasing the bears away from her bird feeders.

The opinions expressed in this blog are those of Sandra Henry-Stocker and do not necessarily represent those of IDG Communications, Inc., its parent, subsidiary or affiliated companies.