- How to Become a Chief Information Officer: CIO Cheat Sheet
- 3 handy upgrades in MacOS 15.1 - especially if AI isn't your thing (like me)
- Your Android device is vulnerable to attack and Google's fix is imminent
- Microsoft's Copilot AI is coming to your Office apps - whether you like it or not
- How to track US election results on your iPhone, iPad or Apple Watch
Turn tabs into spaces on Linux and vice versa
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.
Copyright © 2022 IDG Communications, Inc.