How to read a Specific Line From a File in Linux?


When working with the Linux shell, reading text files is often an important operation. Sometimes, we may be interested in reading a specific line from a file.

We’ll take a look at different ways to get a specific piece of text out of a file.

The actual Problem

Let’s take a look at an example.

let's say we have a file called "test.txt" −

$ nl test.txt
1 This is line 1, I don't have any interesting data.
2 This is line 2, I don't have any interesting data.
3 This is line 3, I don't have any interesting data.
4 This is line 4, I don't have any interesting data.
5 This is line 5, interesting data: Linux is awesome!
6 This is line 6, I don't have any interesting data.
7 This is line 7, I don't have any interesting data.

We've used the nl function to display the contents of the text files with line numbers.

We know that the first four lines contain some interesting information. Therefore, we want only to read the fifth one.

There are many ways of doing that in the Linux command-shell. In this guide, we’ll look at four different methods −

  • Use Bash commands

  • Use sed command

  • Use awk command

  • Use head and tail commands

Let’s take a look at some examples.

Using Bash Commands

To solve the problem we need to write a shell script called getLine.

$ cat getLine.sh
#!/bin/bash
FILE="$1"
LINE_NO=$2
i=0
while read line; do
   i=$(( i + 1 )
   test $i = $LINE_NO && echo "$line";
done <"$FILE"

The shell scripts above accept two arguments: the file name and the target line numbers.

Basically, it consists of a single paragraph. We start by setting the value of $i to zero. Then we check whether the current line matches the one we're targeting (the 10th). If so, we increase $i by 1. Otherwise, we print out the current line.

Command

$ ./getLine.sh test.txt 5

Output

This is line 5, interesting data: Linux is awesome!

The result shows that our script worked.

If we read the text carefully, we might be able to improve it.

We check every single character in the string in the loop, even though we've already found and printed the character we're after. In reality, we might process a whole lot of data before finding what we're looking for. But hey, let's just stick with the example! Our example input contains only seven lines. However in the real world, your input could contain millions of lines.

Therefore, it would be good if we could break out of the cycle once we've found the right line. So, lets change the script a little −

$ cat getLine2.sh
#!/bin/bash
FILE="$1"
LINE_NO=$2
i=0
while read line; do
   i=$(( i + 1 ))
   case $i in $LINE_NO) echo "$line"; break;; esac done <"$FILE"

We've used a case statement to stop the loop when we've found the line we want. Let's see if it works −

Command

$ ./getLine2.sh test.txt 5

Output

This is line 5, interesting data: Linux is awesome!

We've solved the problem by using a little bash scripting.

Use sed Command

The sed commands are pretty good at solving this type of problem. Here are two compact sed one-liners for the job.

Command

$ sed '5!d' test.txt

Output

This is line 5, interesting data: Linux is awesome!

Command

$ sed -n '5p' test.txt

Output

This is line 5, interesting data: Linux is awesome!

To delete all but the fifth (and only) file in a directory, use the following command: 5!dTo just show the fifth (and only), use the following command: -n '5p'

The two one-liner scripts run as we expect them to. However, they will read through the entire input line by line, which takes too long for large files.

The shell script provides a ‘q’ (quit) option for quitting further execution. So we could combine the two commands into one line using the ‘&&’ operator −

Command

$ sed '5!d;q' test.txt

Output

This is line 5, interesting data: Linux is awesome!

Command

$ sed -n '5{p;q}' test.txt

Output

This is line 5, interesting data: Linux is awesome!

We didn't notice any differences between the two outputs so let's use the sed -e's/^.*$//' command to remove everything from the beginning of each line until the end of the line.

Let’s first take a quick glance at the version without the 'q' command.

Command

$ sedsed -d '5!d' test.txt

Output

PATT:This is line 1, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 2, I don't have any interesting data.$
...
This is line 5, interesting data: Linux is awesome!
PATT:This is line 6, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 7, I don't have any interesting data.$
HOLD:$
COMM:5 !d

We can then see that the sed command has processed the file from the first character until the last character (the seventh one)

We’ll now test the sed commands using q.

Command

$ sedsed -d '5!d;q' test.txt

Output

PATT:This is line 1, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 2, I don't have any interesting data.$
...
PATT:This is line 5, interesting data: Linux is awesome!$
HOLD:$
COMM:q
This is line 5, interesting data: Linux is awesome!

The debug output indicates that the sed processing stopped at Line 5.

Use awk Command

Another powerful text processing utility is awk. You can use it to solve the problem with a single line of code: awk 'NR == 5' input.txt.

We don't want to continue processing after printing line 5.

Similarly, awk also has the “quit” command to quit the current processing.

Command

$ awk 'NR==5{ print; exit }' test.txt

Output

This is line 5, interesting data: Linux is awesome!

Therefore, as the output shows, we've solved the problem.

Use head and tail Commands

We can use the `tail` command to extract the last part of a text document.

We can also use the combination of these two commands to read a specific row.

Let's assume we want to read line x. The idea is −

  • We first use the head command to get lines 1 through X from our input file.

  • We then pipe the output from the first step into the tail command to retrieve the last entry: head -n X input | tail -1

Let's see if this idea works for our example −

Command

$ head -n 5 test.txt | tail -1

Output

I am line 5, interesting data: Linux is awesome!

We've got the expected result and we've solved the problem.

Conclusion

We've discussed different ways to read a single row from an input file in Linux.

We've discussed how to improve the performance of the bash, awk, and/or Sed solution.

Updated on: 01-Dec-2022

14K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements