1

I want to remove parts of a file starting from a match (including the first match) and until the second match (excluding the second match). My file looks like this, from another SO question:

3. line 3
4. line 4
## Screenshots ##
1. line 1
2. line 2
3. line 3
4. line 4
## Changelog ##
3. line 3
4. line 4

From the answers of the other question I have taken a sed command that outputs from ## Screenshots ## until 4. line 4, just before ## Changelog ##. However, I would like to remove that section from the file.

To clarify, I only know that the next section will start with ##, it could be ## foobar ## for all I know :)

I have tried to replace the print commands by delete commands like so

sed -e '/## Screensh/,/##/{/Scree/{d;n};/##/{q};d}' file

but that did not work because it stops output after the second match, ## Changelog ## in this case (because of the quit command). I have also tried to use a regex character class to match anything but a # character like sed -n '/## Screenshots ##[^#]*/p' but that only prints ## Screenshots ##.

Community
  • 1
  • 1
Zsub
  • 1,799
  • 2
  • 15
  • 28

3 Answers3

4

Something like this:

sed '/## Screenshot/,/##/{/Screenshot/d;/##/!d}'

That's it - delete everything between two matches, including the first but not including the last. If you know that the section ends with '## Changelog ##' it becomes just

sed '/## Screenshot/,/##/{/## Changelog/!d}'
aragaer
  • 17,238
  • 6
  • 47
  • 49
  • Isn't your solution also a simpler version of the script to output the section if used with -n? As in: `sed -n '/## Screenshot/,/##/{/Screenshot/p;/##/!p}'`? – Zsub Mar 13 '14 at 12:50
  • Not sure if I should re-ask, but I'd actually like to use bash variables inside the expression. This means changing the quotes to double-quotes and this, in turn, makes `!` a character I need to escape for my shell, but `sed -i "/## Screenshot${var}/,/##/{/Screenshot${var}/d;/##/\!d}" file` complains about `\` being an unknown command :( – Zsub Mar 13 '14 at 13:01
  • 1
    I have played with it for a bit and it seems sed is ok to have an argument which consists of several concatenated strings: `sed "something"'!'"something else"` worked for me. – aragaer Mar 13 '14 at 13:06
  • *Edit: thanks!* Oh, got it, just have to use double and single quotes in the same command, according to http://superuser.com/a/301330/31926 – Zsub Mar 13 '14 at 13:07
1

A sed version:

sed '/## Screenshot/,/## Changelog/d' file
3. line 3
4. line 4
3. line 3
4. line 4

And an awk version

awk '/## Screenshots/{f=1;next} !f; /## Changelog/{f=0}' file
3. line 3
4. line 4
3. line 3
4. line 4
Jotne
  • 40,548
  • 12
  • 51
  • 55
  • 1
    or `awk '/## Screenshots/,/## Changelog/{next}1' file` – jaypal singh Mar 13 '14 at 12:58
  • @jaypal I have not seen this before, thanks. Normally I try to avoid the `/to/,/from/` in `awk` since it limits some the for other test. For simple task `,` is fine. – Jotne Mar 13 '14 at 13:36
1
$ sed '/## Screenshots ##/,/## Changelog ##/d' test.txt
3. line 3
4. line 4
3. line 3
4. line 4
Adrian Frühwirth
  • 42,970
  • 10
  • 60
  • 71