It not a joke!!! It is the truth!!!

Giving people what they want: violence and sloppy eating

Previous Entry Share Next Entry
Lazyweb - awk
mini me + poo
A bash script I use ends by displaying a line it wants you to add to another file. It would obviously be easier if the script did this itself. As the line will be somewhere in the middle of the file, just using '>>' to append it is no good.

Somewhere :) I have (or had) The AWK Programming Language and my Google skills are enough to be reminded that:

awk '/NEW STUFF HERE/ {print;print "my new line";next}1' test-file

will add 'my new line' after 'NEW STUFF HERE'.

Now, 'my new line' needs to have a number in it that is different to all the other such lines (it's an array index).

Can someone remind me of a good way to do that? The line count of the entire file prior to adding the line would be fine, for example.

  • 1
Once I'd remembered that you don't stick $ in front of AWK variables, and that it'd be better to have them before the sentinel string...

awk '/END SENTINEL/ {print "This ["FNR"] is my new line";print;next}1' test-file

.. FNR = the line number, effectively.

So you get

forty-odd lines of blah
This [42] is my new line
more blah

Then all you have to do is remember you have to write it to a temporary file and move over the original rather than writing to the original. (A good way to delete your original!)

This solution has the new line and your insertion point in the other way round compared to the original post. If that's what you need then just switch the first print and the if block in my program.

This way, I get to use the line number as the unique array index. If it were inserted as in the first one, the line number at that point would always be the same.

I don't know awk well enough so have an over-engineered perl solution instead

use strict;
use warnings;

my @text            = ;
my $multipleinserts = 0;
my $alreadyseen     = 0;

for (my $i = 0 ; $i < $. ; $i++) {
        print $text[$i];
        if ($text[$i] =~ /pattern to insert after/ && $multipleinserts || !$alreadyseen) {
                print 1+$. .": new line here\n";
                $alreadyseen = 1;

If the search patter appears twice then the text gets inserted after the first, or you can edit the obviously named variable to have it inserted after every occurrence. You didn't state what format the numbers take so I guessed. It shouldn't be too hard to change to suit your requirements. One caveat - it doesn't check for duplicate index values.

This is Amongst the reasons I like the command line so much is that there are so many ways of doing something, almost all of which are easier than doing the same thing the WIMPy way, and some of them are so elegant.

I'm not sure of the strict requirements for the numbers, I just know that natural numbers work and they don't need to be sequential (although my second solution will make them so) or start at any number in particular. Neither does mine :)

Quick reminder to self that to print a ' character, use \x27

There are other ways, but this is the easiest.

  • 1

Log in

No account? Create an account