Nugget Post : Beyond basic SED

Interesting problem to solve with sed. Given the following file:

[firstCompany-1-restricted-internal]
exten => _1XX,1,Goto,(from-internal,${EXTEN},1)
exten => _881XX,1,Goto(from-internal,${EXTEN},1)
exten => _XXX,1,Goto(app-blackhole,congestion,1)
exten => _XXXXX,1,Goto(app-blackhole,congestion,1)
exten => _9XXXX.,1,Dial(SIP/BRI_1_OUT/${EXTEN},60)
exten => h,1,Hangup()

[secondCompany-2-restricted-internal]
exten => _2XX,1,Goto,(from-internal,${EXTEN},1)
exten => _882XX,1,Goto(from-internal,${EXTEN},1)
exten => _XXX,1,Goto(app-blackhole,congestion,1)
exten => _XXXXX,1,Goto(app-blackhole,congestion,1)
exten => _[*0-9]!,1,Set(restprefix=1001992)
exten => _[*0-9]!,1,Goto(from-internal,${restprefix}${EXTEN},1)
exten => h,1,Hangup()

We’d like to be able to delete the first paragraph. With sed, this is possible using something like:

sed ‘/^\[firstCompany/,/^\[/{/^\[firstCompany\|^e/d}’

Breaking this down we see the following expression (with extra spacing for readability):

/  ^\[firstCompany  /      ,         /  ^\[  /

The standard sed delimeters of “/” can be seen enclosing two elements, separated by a comma. The first element matches any line beginning with “[firstCompany” (note the escaping via the \ character). The second element matches any line beginning with “[“. The comma between them means “match all lines between”. So this expression matches all the lines:

[firstCompany-1-restricted-internal]
exten => _1XX,1,Goto,(from-internal,${EXTEN},1)
exten => _881XX,1,Goto(from-internal,${EXTEN},1)
exten => _XXX,1,Goto(app-blackhole,congestion,1)
exten => _XXXXX,1,Goto(app-blackhole,congestion,1)
exten => _9XXXX.,1,Dial(SIP/BRI_1_OUT/${EXTEN},60)
exten => h,1,Hangup()

[secondCompany-2-restricted-internal]

This block of text is passed to the next expression (via curly brackets…imagine that the { } symbols serve as a container for all previously matched text). The expression within the curly brackets consists of:

/        ^\[firstCompany\ | ^e        /d

This basically means match any line beginning with “[firstCompany” OR (the “|” symbol) any line beginning with “e”. The expression ends with “d”, which instructs sed to delete the matched lines.

So the above expression operates on the text previously matched by the first expression and gives us the desired result:

[secondCompany-2-restricted-internal]
exten => _2XX,1,Goto,(from-internal,${EXTEN},1)
exten => _882XX,1,Goto(from-internal,${EXTEN},1)
exten => _XXX,1,Goto(app-blackhole,congestion,1)
exten => _XXXXX,1,Goto(app-blackhole,congestion,1)
exten => _[*0-9]!,1,Set(restprefix=1001992)
exten => _[*0-9]!,1,Goto(from-internal,${restprefix}${EXTEN},1)
exten => h,1,Hangup()