7

Content of my filename file is as following(for example):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

I want to replace block of lines between START and END with just a single word, for example with SINGLEWORD. Like below:

My block of line starts from here 
SINGLEWORD
and end to here for example.

I can find my block of lines with using this command:

grep -Pzo "START(.|\n)*END" filename

And the result of running above command will be like this:

START
First line
second line
third line
END

Then I used this command to combine all lines into a single line:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

Then I will get this result:

START First line second line third line END

And with my last command LAST_RESULTS | sed 's/.*/SINGLEWORD/' I change them to "SINGLEWORD" and I get this result.

SINGLEWORD

Now what I want is: How can I use this command(Or your suggestion command) and replace(in place)my block of lines to "SINGLEWORD" word? And the final result will be like this file:

My block of line starts from here 
SINGLEWORD
and end to here for example.
10

This can be done very easily in perl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

Explanation

-0 sets the line separator to null

-p apply the script given by -e to each line and print that line

The regexp modifier:

  • /s Treat string as single line. That is, change . to match any character whatsoever, even a newline, which normally it would not match.

Why the ?:

  • By default, a quantified subpattern is "greedy", that is, it will match as many times as possible (given a particular starting location) while still allowing the rest of the pattern to match. If you want it to match the minimum number of times possible, follow the quantifier with a ?.
  • @KasiyA: Using sed should be possible but probably harder to read (Look at this question) – Sylvain Pineau Oct 7 '14 at 16:05
  • One more because my START and END pattern has special chars(/,*,?) in it and these are just example. and could you explain your command. – αғsнιη Oct 7 '14 at 16:08
  • @KasiyA you can escape such characters with \ (exactly as with sed): \/, \*, \? – Sylvain Pineau Oct 7 '14 at 16:13
  • @KasiyA I tried perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. It should work – Sylvain Pineau Oct 7 '14 at 16:35
  • @KasiyA I think I'm done with explanations now ;) – Sylvain Pineau Oct 7 '14 at 16:54
12

I was wondering if this is possible without perl, python and others. And I found this solution using sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

Explanation:

  1. :a create a label 'a'
  2. N append the next line to the pattern space
  3. $! if not the last line, ba branch (go to) label 'a'
  4. s substitute, /START.*END/ by SINGLEWORD,/g global match (as many times as it can)

It was found here.

@KasiyA, thank you I learned a lot of interesting things!

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.