0

I am using this sed

sed -i "/^### Header$/,/^### [^#]*$/{//!d}"

This sed deleted all the text between Header to Header 2. I want only to delete the text for the first matched range.

Note I don't know what is the title of the next Header!

Input:

### Header

blabla

### Header 2 

some text 

### Header

blabla

### Header 2 

some text 

### Header

blabla

### Header 2 

some text 

output:

### Header
### Header 2 

some text 

### Header

blabla

### Header 2 

some text 

### Header

blabla

### Header 2 

some text 
KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • 1
    This is usually simpler with awk. https://stackoverflow.com/questions/22277869/sed-search-a-range-and-print-first-set – KamilCuk May 22 '23 at 07:36

2 Answers2

3

Using GNU sed

$ sed '/^### Header$/,/^###/{1,/^###/{//!d}}' input_file
### Header
### Header 2

some text

### Header

blabla

### Header 2

some text

### Header

blabla

### Header 2

some text
HatLess
  • 10,622
  • 5
  • 14
  • 32
0

sed is an excellent tool for doing s/old/new/ on simple strings, for anything else just use awk for some combination of clarity, portability, robustness, efficiency, etc. In this case, using any awk in any shell on every Unix box:

$ awk '/^### [^#]/{inRange=0} !inRange{print} /^### Header$/ && (++cnt==1){inRange=1}' file
### Header
### Header 2

some text

### Header

blabla

### Header 2

some text

### Header

blabla

### Header 2

some text

Note that by using a flag variable inRange you don't have to test the start or end of the range twice as is common if you use a range operator, see Is a /start/,/end/ range expression ever useful in awk?, and by using a counter variable cnt you could trivially change the code to operate on the 2nd or 10th or any other occurrence of the range instead of or in addition to the first occurrence. sed doesn't have variables.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185