How to delete 1 line before and after a matched line, and the matched line itself?

Viewed 86

I have this file:

root@DESKTOP-PDVDCNC:/var/tmp# cat test.txt
    monitoring:
      email: ''
      enabled: true
      full_name: Kibana Application server
      metadata: {}
      roles: [ReadAllIndices]
      username: monitoring
    nagios:
      email: null
      enabled: true
      full_name: Nagios Monitoring
      metadata: {}
      roles: [read_only]
      username: nagios
    monitor_stream_user:
      email: null
      enabled: true
      full_name: null
      metadata: {_reserved: true}
      roles: [monitor_stream_collector, monitor_stream_agent]
      username: monitor_stream_user
    H4410603:
      email: null
      enabled: true
      full_name: "John Doe"
      metadata: {}
      roles: [group1, group2, app_food, group3, group4, group5, application_memory]
      username: H4410607
    Q6655060:
      email: jules_sayzan@carrefour.com
      enabled: true
      full_name: "Jules"
      metadata: {}
      roles: [group1, group2, app_food, group3, group5, application_memory]
      username: Q6655060
    A1090501:
      email: ''
      enabled: true
      full_name: "Ruth Beneth"
      metadata: {}
      roles: [application_memory]
      username: A1090507

and I want to delete 1 line before and after a matched line, and the matched line itself.

The matched line is : every line that contains: "group3" string.

I have try this with no sucess:

root@DESKTOP-PDVDCNC:/var/tmp# cat test.txt |sed -zE 's/([^\n]*\n){1}([^\n]*group3[^\n]*)(\n[^\n]*){1}/\2/g'

4 Answers

Could you please try following. Written on mobile couldn't test it should work I believe will test in few mins or so.

awk '
FNR==NR{
  if($0~/group3/){
    negLine[FNR-1]
    negLine[FNR]
    negLine[FNR+1]
  }
  next
}
!(FNR in negLine)
' Input_file  Input_file

Explanation: Adding detailed explanation for above.

awk '                       ##Starting awk program from here.
FNR==NR{                    ##Checking condition if FNR==NR which will be true when first time Input_file is being read.
  if($0~/group3/){          ##Checking condition if line has group3 in it then do following.
    negLine[FNR-1]          ##Creating negLine with index of previous number number in it. 
    negLine[FNR]            ##Creating negLine with index of current line number in it.
    negLine[FNR+1]          ##Creating negLine with next line of current line number in it.
  }
    next                    ##next will skip all further statements from here.
}
!(FNR in negLine)           ##Checking condition if current line number is NOT prsent in negLine then print that line.
' Input_file  Input_file    ##Mentioning Input_file name here.

Another awk by reading the file once.

awk  ' { 
if($0~/group3/) { getline; getline; } 
else { if(NR>1) print b } 
b=$0 
} 
END { print b } ' group3.txt

Print the first line when are reading the second line. getline would read the next line. b=$0 stores the prior value.

Here a solution with grep and sed:

FILE=test.txt
for i in $(cat $FILE | grep -n group3 | cut -d: -f1 | tac) ; do
    prev=$((i - 1))
    next=$((i + 1))
    sed -i "$prev,${next}d" $FILE
done

This might work for you (GNU sed):

sed ':a;N;s/\n/&/2;Ta;/\n.*group3.*\n/d;P;D' file

Make a window of 3 lines throughout the file and if the second line contains group3 delete the window.

For consecutive matches, use:

sed ':a;N;s/\n/&/2;Ta;/\n.*\(group3\).*\n.*\1/D;/\n.*group3.*\n/d;P;D' file
Related