1. Overview
Managing and manipulating text files on Linux is a common responsibility for system administrators. One such task may involve replacing a string on a specific line number across multiple files. This can be useful in modifying configuration files, updating scripts, or processing data.
In this tutorial, we’ll explore different methods of replacing a string on the nth line in multiple text files using the sed, awk, and perl commands in the Linux terminal.
2. Using the sed Command
sed is a text processing tool used to parse and transform text. Additionally, we can use it to perform basic text manipulation such as searching, replacing, and deleting lines on an input stream. In this case, we’ll use it to replace a string on a specific line in multiple files. Furthermore, we’ll use sed in combination with the find command.
Before we begin, let’s check the syntax we’ll use:
$ sed -i 'Ns/old_string/new_string/' filename
- -i – represents an in-place option that instructs sed to edit the file directly
- N – specifies the line number where the substitution will take place
- s/old_string/new_string/’ – represents a substitution command that replaces the old_string with the new_string on the specified line
- filename – specifies the name of the file we want to process
Now, let’s use sed to replace a string on the nth line of multiple text files:
$ find . -type f -name '*.txt' -exec sed -i '2s/yahoo/gmail/' {} +
Let’s examine the above command:
- find . -type f -name ‘*.txt’ – searches for all .txt files in the present working directory and its subdirectories
- -exec – represents an option that allows us to execute a command on each file that find matches
- sed -i ‘2s/yahoo/gmail/’ {} + – replaces the string yahoo with gmail on the second line of each file
Above, we replace the string yahoo with gmail on the second line of each file. Moreover, only the first occurrence of the string yahoo is replaced.
To replace all occurrences of yahoo on the second line, we use the g flag:
$ find . -type f -name '*.txt' -exec sed -i '2s/yahoo/gmail/g' {} +
Here, we add the g flag to the sed command, enabling us to replace multiple occurrences of the string yahoo with gmail on the second line.
2.1. Replacing Multiple Strings on the Nth Line in Multiple Files
Furthermore, we can use multiple sed commands to replace multiple strings on the same line by separating the commands with a semicolon:
$ find . -type f -name "*.txt" -exec sed -i '2s/Email/EmailAddress/; 2s/yahoo/gmail/' {} +
The above command replaces multiple strings on the second line of each file. To explain, 2s/Email/EmailAddress/ replaces the string Email with EmailAddress while 2s/yahoo/gmail/ replaces the string yahoo with gmail.
3. Using the awk Command
awk is a command line tool used to process text and extract data. Unlike sed, awk is more flexible, especially when we need to perform complex pattern matching and replacement.
First, let’s check the syntax we’ll use:
$ awk '{ if (NR == N) sub(/old_string/, "new_string"); print }' filename > temp && mv temp filename
Let’s break down the above syntax:
- if (NR == N) – represents a condition that checks if the current line number NR is equal to the specified line number N
- sub(/old_string/, “new_string”); – represents a substitution function used to replace the first occurrence of old_string to new_string on the current line
- print – prints the current line
- filename – represents the input file awk will process
- > temp – redirects the output of awk to a temporary file named temp
- && – specifies a logical AND operator that ensures the next command runs only if the previous command succeeds
- mv temp filename – moves the temporary file temp to the original filename replacing the original file with the modified version
To clarify, since awk doesn’t modify files in place, we need to redirect the output to a temporary file and then move it back.
3.1. Replacing a String on the Same Line in Multiple Files
To demonstrate, let’s replace a specific string on the 6th line:
$ find . -type f -name "*.txt" -exec sh -c 'for file; do awk "{ if (NR == 6) sub(/DOB/, \"Date_Of_Birth\"); print }" "$file" > temp && mv temp "$file"; done' sh {} +
Let’s understand the above command:
- find . -type f -name “*.txt” – searches for all .txt files in the current directory and its subdirectories
- -exec sh -c ‘…’ sh {} + – executes a shell command on the files we find
- for file; do … done – represents a for loop used to iterate over each file passed to the script
- awk “{ if (NR == 6) sub(/DOB/, \”Date_Of_Birth\”); print }” “$file” – replaces the string DOB with Date_Of_Birth on the sixth line
Above, we replace the string DOB with Date_Of_Birth on the 6th line of each file.
By default, the sub-function replaces only the first occurrence of the string in a line. So, to replace all occurrences of the string in the nth line, we use the gsub function:
$ find . -type f -name "*.txt" -exec sh -c 'for file; do awk "{ if (NR == 2) gsub(/gmail/, \"yahoo\"); print }" "$file" > temp && mv temp "$file"; done' sh {} +
Here, we replace all occurrences of the string gmail with yahoo on the second line of each file.
3.2. Replacing Multiple Strings on the Same Line
In addition, we can replace multiple strings on the same line:
$ find . -type f -name "*.txt" -exec sh -c 'for file; do awk "{ if (NR == 2) { gsub(/EmailAddress/, \"Email\"); gsub(/yahoo/, \"gmail\"); } print }" "$file" > temp && mv temp "$file"; done' sh {} +
Above, we use multiple awk commands separated by a semicolon to replace multiple strings on the same line on each file.
3.3. Combining Multiple Conditions
Furthermore, we can perform different actions based on multiple conditions within the same command using awk. For instance, let’s replace specific strings on different lines in multiple files:
$ find . -type f -name "*.txt" -exec sh -c 'for file; do awk "NR == 2 { gsub(/yahoo/, \"gmail\") } NR == 7 { gsub(/AdmissionNumber/, \"AdmnNo\") } { print }" "$file" > temp && mv temp "$file"; done' sh {} +
Let’s explain the above command:
- NR == 2 { gsub(/yahoo/, \”gmail\”) } – replaces yahoo with gmail on the second line on each file
- NR == 7 { gsub(/AdmissionNumber/, \”AdmnNo\”) } – replaces AdmissionNumber with AdmnNo on the seventh line of each file
To explain, the above command replaces specific strings in multiple files on the second and seventh lines.
4. Using the perl Command
perl is a command line tool used to extract information from text files. Additionally, we can use it to perform complex text manipulations. Here, we’ll use it to replace a string on the nth line.
Firstly, let’s check the syntax we’ll use:
$ perl -i -pe 's/old_string/new_string/ if $. == N' filename
Let’s understand the above syntax:
- -i – enables in-place editing of files
- -pe – the -p option instructs perl to loop over the input file line by line, while the -e option allows us to provide a perl script to be executed directly on the command line
- s/old_string/new_string/ – represents a substitution command used to replace the old_string with new_string
- if $. == N – this condition ensures the substitution only occurs if the current line number equals the nth line
Now, let’s replace a string on the nth line of multiple files.
4.1. Replacing a String on the Nth Line in Multiple Files
To illustrate, we’ll replace a string on the first line of each file. We’ll use perl in combination with the find command:
$ find . -type f -name "*.txt" -exec perl -i -pe 's/Name/FullName/ if $. == 1' {} \;
In the example above, find locates all text files in the current directory and its subdirectories. We then use perl to replace the first occurrence of the string Name in the first line of each file with FullName.
Furthermore, we can replace all occurrences of Name, using the g flag:
$ find . -type f -name "*.txt" -exec perl -i -pe 's/Name/FullName/g if $. == 1' {} \;
The above command replaces all occurrences of the string Name in the first line of each file.
4.2. Replacing Multiple Strings on the Nth Line
Additionally, we can perform multiple string substitutions on the same line by chaining the substitution commands:
$ find . -type f -name "*.txt" -exec perl -i -pe 's/Email/EmailAddress/g if $. == 2; s/gmail/yahoo/g if $. == 2' {} \;
Above, we replace Email with EmailAddress and gmail with yahoo on the second line of each file.
5. Conclusion
In this article, we discussed replacing a string on the nth line of multiple files in Linux. We utilized the sed, awk, and perl commands. Further, we combined these commands with the find command to search for text files in the specified directory and its subdirectories.