0

Similar to a question posted by me here earlier, am looking for a help in Linux command that performs/does the following that is subtle different from my original question:

Searches for a particular word/phrase case-insensitively in a given file, and then insert/prefix with the character -- (in this case, this is an SQL comment) in the immediate next 'n' lines including the line where the word/phrase was matched in the given file.

EXAMPLE: If I try to search for the phrase "CREATE FUNCTION plpgsql_call_handler" case-insensitively and if it matches at line no.102644, then I expect to insert/prefix the character -- in line no.102644 and the immediate next 2 lines in the given file. In this case, I expect to insert/prefix line nos. 102644,102645,102646 with the character --.

Example file:

102644 CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler
102645     AS '/usr/lib/pgsql/plpgsql.so', 'plpgsql_call_handler'
102646     LANGUAGE c;

I expect/want it to be changed into (in this case, it is an SQL comment):

102644 -- CREATE FUNCTION plpgsql_call_handler() RETURNS language_handler
102645 --    AS '/usr/lib/pgsql/plpgsql.so', 'plpgsql_call_handler'
102646 --    LANGUAGE c;

3 Answers 3

1

This is how you'd do it in-place with sed:

sed -r -i -e '/CREATE FUNCTION plpgsql_call_handler/I,+2 s/^/-- /'

(May require GNU sed.)

Replace 2 with the number of lines you want (or use any other sed address forms).

This is much simpler than that perl monstrosity. Also, perl could do it in place by using the -i as well:

perl -i -n -e horrible_perl_code /path/to/file

In both cases if you wish to keep a backup change -i to -i.bak.

1
  • Yes, it's working as I expected. It's more easy & readable than perl syntax provided by @MadHatter.
    – Gnanam
    Apr 12, 2011 at 4:41
0

And yet again, the ol' Swiss Army Chainsaw revs into life:

perl -n -e 'if (/create/i) { s/^(\d+)/\1 --/; print $_; $_=<> ; s/^(\d+)/\1 --/; print $_; $_=<> ; s/^(\d+)/\1 --/; print $_; } else { print $_; }' < /path/to/file

It's not as horrible as it looks! perl -n -e does a loop around each line in the file, not implicitly printing the line, and running the little perl script supplied, on each line.

The little script supplied looks for a string (here it's create, but you can change it as you like) in each line, matching case-insensitively (/i). When it finds the string, it:

  1. replaces all the immediately-sequential digits at the beginning of a line ( ^(\d+) ) with themselves (\1) plus " --",
  2. prints the modified line
  3. reads the next line in ($_=<>)and repeats steps 1 and 2 on that line
  4. reads the next line in and repeats steps 1 and 2 on that line

If the line doesn't contain that string, it prints it unmodified.

I'm sure this could be optimised further, but hopefully that'll do what you want. It sends the modified file to STDOUT; capturing that to a temp file and moving it over the original is left as a (trivial) exercise for the OP!

6
  • @MadHatter: Could you provide awk/sed equivalent that does the same in place?
    – Gnanam
    Apr 11, 2011 at 13:14
  • No. awk won't do that, and sed's not my favourite tool. Are you asking for that because this is a homework question, or do you have a genuine business need to do it in place which doing it to a temporary file and moving that into place won't satisfy?
    – MadHatter
    Apr 11, 2011 at 13:16
  • @MadHatter: Only 2 reasons: 1) I thought awk/sed may have a simplified/ readable format. 2) In fact, I need to do this (modification) exercise in all our different onsite customer servers, so I'm seeing whether this could help me in making this operation in place (in the same input file passed), like the one I've asked before (on deleting).
    – Gnanam
    Apr 11, 2011 at 13:28
  • With regard to point 2, I fail to understand the functional difference between operating on a file in place and operating on a file to a temporary copy and moving that copy into place, given appropriate checks on the success of each of the steps. You have also been told in the comments to your earlier question (referenced above) that awk won't easily make changes in situ, either. Perhaps someone with more sed experience can provide you with an incantation suitable for that tool, so we can compare complexity with regard to point 1?
    – MadHatter
    Apr 11, 2011 at 13:33
  • @MadHatter: No issues. I can follow your steps also. But this is just for my understanding, can this not be performed in place using perl?
    – Gnanam
    Apr 11, 2011 at 13:45
0

AWK example:

awk 'tolower($0) ~ /create function plpgsql_call_handler/ {n=3;} // { if (n-->0) printf "-- "; print $0;}'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .