How to reverse file content using sed command ?

In this post, we will at an interesting way how to reverse a file content using sed(stream editor) command.

I. TAC Command: Command to reverse file content.

### Create a sample file with below content.
[root@nglinux ]# cat file1 
A
B
C
[root@nglinux ]# 

### Run "tac filename" to reverse its contents.
[root@nglinux testdir]# tac file1 
C
B
A
[root@nglinux testdir]# 

 

II. Reverse file content using sed

[root@nglinux ]# sed '1!G;h;$!d' file1 
C
B
A

 

III. Understanding above sed command options

[root@nglinux ]# sed '1!G;h;$!d' file1 
C
B
A  

Options
1!     Omits First line
g G    Copy/append hold space to pattern space.
h H    Copy/append pattern space to hold space.
$!     Deletes last line

 

IV. Explanation

General
1. sed command has a hold space & a pattern space.
We have to understand them before actually examining above command.

 

2. When sed reads a line, it is loaded into its pattern space.
Hence pattern space is overwritten every time a new line is processed.

Hold space is consistent over the complete processing and values are stored there for usage afterwards.

 

Above Command Options
3. Now, when first line from the file1 is read, sed executes the h command.
The first line is then copied into hold space. Then “\n” is deleted from pattern space, since it matches the $! condition.
Hold space = “A”
Pattern space = “A \n” ## \n is deleted by $!d
sed continues with the second line.

 

4. The second line matches the condition 1! ( as it’s not the first line).
And hence the hold space (which has first line) is appended to the pattern space (which has the second line).

Now in the pattern space, there is second line followed by the first line, delimited by newline.
At this point, h command applies and all pattern space data is copied to the hold space.
In the end, third statement ($!d) applies: The line is deleted from the pattern space.

Before:
Hold space : “A” ## \n is deleted by $!d
Pattern space : “B \n”

After:
Pattern space: “B \n”
Hold Space: “B \n A”

 

5. Similarly after 3rd line, we have following pattern and hold space data.
Before:
Pattern space: “B \n”
Hold Space: “B \n A”

After:
Hold space : “C \n” ## \n is not deleted by $!d as it is last line
Pattern space : “C \n B \n A ”

Step 4 is now done with all lines.
Last line is also processed similarly except the newline character is not deleted from it.

In the end, pattern space is printed which contains all lines in reversed order.

 

6. Lets see how the pattern space is processed and printed below.

### Copies pattern space into hold space.
### and then appends hold space into pattern space.
### Pattern space is printed below.
[root@nglinux testdir]# sed 'G;h' file1 
A

B
A

C
B
A

### When we omit the processing of first line.
[root@nglinux testdir]# sed '1!G;h' file1 
A
B
A
C
B
A

Leave a Reply

avatar
  Subscribe  
Notify of