I want to replace the 5th line of multiple text files (file1.txt,file2.txt,file3.txt,file4.txt) with the string " Good Morning " using a single terminal command.
All the text files are located on my ~/Desktop
.
Note: My desktop consists of 6 .txt files.I want to apply the change to above mentioned 4 text files only.
Here are a few approaches. I am using brace expansion (
file{1..4}.txt
) which meansfile1.txt file2.txt file3.txt file4.txt
Perl
Explanation:
-i
: causesperl
to edit the files in place, changing the original file.If
-i
is followed with a file extension suffix, then a backup is created for every file that is modified. Ex:-i.bak
creates afile1.txt.bak
iffile1.txt
is modified during the execution.-p
: means read the input file line by line, apply the script and print it.-e
: allows you to pass a script from the command line.s/.*/ Good Morning /
: That will replace the text in the current line (.*
) with Good Morning.$.
is a special Perl variable that holds the current line number of the input file. So,s/foo/bar/ if $.==5
, means replacefoo
withbar
only on the 5th line.sed
Explanation:
-i
: Like forperl
, edit file in place.By default,
sed
prints each line of the input file. The5s/pattern/replacement/
means substitute pattern with replacement on the 5th line.Awk
Explanation:
awk
has no equivalent to the-i
option¹ which means that we need to create a temporary file (foobar
) which is then renamed to overwrite the original. The bash loopfor f in file{1..4}.txt; do ... ; done
simply goes through each offile{1..4}.txt
, saving the current file name as$f
. Inawk
,NR
is the current line number and$0
is the content of the current line. So, the script will replace the line ($0
) with " Good Morning " only on the 5th line.1;
isawk
for "print the line".¹Newer versions do as devnull showed in his answer.
coreutils
Explanation:
The loop is explained in the previous section.
head -4
: print the first 4 linesecho " Good Morning "
: print " Good Morning "tail -n +6
: print everything from the 6th line to the end of the fileThe parentheses
( )
around those three commands allow you to capture the output of all three (so, 1st 4 lines, then " Good morning ", then the rest of the lines) and redirect them to a file.You could use
sed
:would append
Good morning
on the fifth line of a file.If you want to replace the contents on line 5 instead, say:
If you wanted to save the changes to the file in-place, use the
-i
option:sed
can handle more than one file at a time. You can just add more filenames onto the end of the command. You can also use bash expansions to match particular files:You can read more about brace expansions here.
GNU awk versions 4.1.0 and higher come with an extension that enable in-place editing. So you could say:
to replace line #5 in the file with
Good morning
!I didn't see python solution so here it is:
Basic idea is that for each file provided on command-line as argument, we write out a temporary file and enumerate each line in the original file. If index of the line is 5, we write out line that is different. The rest is just replacing old file with temp file Demo:
The same can be achieved with list comprehension. Below is a one-liner of the same script:
or without
cat
What is left there is to simply redirect output of edited contents into another file with
> output.txt
You can use Vim in Ex mode:
5
select 5th linec
replace textx
write if changes have been made (they have) and quitThe following is a bash script which wraps up the perl process suggested in this answer
Example:
/tmp/it
Then run the following:
and the file now contains
/tmp/it
search_and_replace_on_line_of_file.sh