How can I insert some text in specific lines of a file? What is the simplest method that I can use? (bash, sed, awk?)
What I want to do might be simple, but I don’t know where I should start. It takes too much time for me to try to do this manually (I have a lot of files that I have to change for Excel/Calc later use).
Here is my input file example:
4.06
4.05
5.04
4.06
34.50
56.06
45.33
36.44
And I want something like this (insert text before line 1 and 5):
Exp1
4.06
4.05
5.04
4.06
Exp2
34.50
56.06
45.33
36.44
How can I do this?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
awk 'NR==1{print "Exp1"}NR==5{print "Exp2"}1' file
1 at the end means {print}.
sed '1i Exp1 5i Exp2 ' file
If you want to extend it to more numbers, awk makes that easy:
awk 'NR%4==1{print "Exp"++i}1' file
With different numbers, we’ll just say sed isn’t the right tool for the job. It’s possible, but not pretty.
As an academic curiosity, here it is in sed:
sed '1{
h
s/^.*$/Exp0/
x
}
x
s/^4//
s/^3/4/
s/^2/3/
s/^1/2/
/^E/ {
s/$/|/
:x
s/0|/1/
s/1|/2/
s/2|/3/
s/3|/4/
s/4|/5/
s/5|/6/
s/6|/7/
s/7|/8/
s/8|/9/
s/9|/|0/
tx
s/^Exp|/Exp1/
p
s/^/1/
}
x' file
Method 2
If the number of data points (I’m assuming) in each of your experiments (again, I’m assuming) is always 4, you can use this Perl one-liner:
perl -ple '$. % 4 == 1 and print "Exp", ++$i' your_file
How it works
- The
-pswitch tells Perl to loop over the given file(s) line by line (by default) and print each line after executing whatever code you supply. - The
-lswitch tells Perl to automatically append a newline (by default) to eachprintstatement. - The
-eswitch informs Perl that whatever comes after it is code to execute (the code that will be executed before each line of the file is printed). - The special variable
$.holds the line number currently being processed. If that line number is congruent to 1 modulo 4 ($. % 4 = 1) it means that we need to insertExp #before it. - So we test
$. % 4 == 1and if it’s true, we printExp ++$in(wherenwas added by the-lswitch). This works because an undefined variable is given a value of zero by Perl when it’s first used as an integer.
To make it work with multiple files
-
The
$.variable will not reset its value if you’re processing multiple files at once. Obviously, this is not what you want. You can work around this by explicitly writing out the implicit loop created by-pin the above one-liner so you can manipulate thecontinueblock.perl -le ' while(<>){ $. % 4 == 1 and print "Exp ",++$i } continue { print; # Print the current line if(eof){ # If the next line is the end-of-file close ARGV ; # Close the current filehandle to reset $. $i = 0 ; # Reset the experiment counter if you need } } ' list_of_your_files
Notes
-
Both of the above solutions will print the modified file(s) to standard output. To emulate an edit in place (i.e. edit the files themselves), add a
-iswitch:perl -pi -le '$. % 4 == 1 and print "Exp", ++$i' your_file
- Proceed similarly for the other solution.
-
Make sure you don’t put another switch directly after
-ias it interprets anything after it as the extension to use in order to create a backup file. -
I recommend you test without
-ifirst and then add it if the results are satisfactory.
Method 3
You don’t need external languages, a few standard commands can do the trick. For example, to insert something at line 5 of origin.txt you could do:
tmpfile=`mktemp` head -n4 origin.txt > $tmpfile echo "I'm line 5 now" >> $tmpfile tail -n +5 origin.txt >> $tmpfile mv $tmpfile origin.txt
Method 4
Combine head and tail
cat <(head -n4 input) <(echo 'Line 5!') <(tail -n +5 input) > output
Replace input with your input file and output with your output file.
Advantages of this method:
- Lets you insert text from a third file: just replace
echo line 5!withcat file-to-insert.txt - No lengthy inscrutable syntax
- No external software that might not be available (
awk,sed,perl) - Supports multiline insertions (harder with
awkandsed)
Disadvantages for the specific situation in question:
- It gets more complicated if you need multiple insertions
Method 5
I found this question searching for a way to add a comment (#) symbol to the start of a nominated line in a file. Using the above example and a few others I found this is the awk command to print something at a nominated line.
awk 'NR==1{print "#"$0; next}1' <file
The NR==1 is the line to consider.
print "#" is what to add
$0 inserts to a string containing the rest of the line at the number provided next tells it to skip that line (having printed it, otherwise you get it twice)
and as mentioned above, the trailing 1 inserts the rest of the file.
Method 6
Perl one liner command will solve this:
perl -i -lpe 'print "the line content" if $. == lineNumber' file_name.txt
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0