Delete lines: after pattern1 and between pattern2 and pattern3 using awk / sed / perl

I need to delete lines from a file after pattern1 and between pattern 2 and pattern 3 , as shown below:

aaaaaaaa 
bbbbbbbb
pattern1   <-----After this line
cdededed
ddededed
pattern2
fefefefe   <-----Delete this line
efefefef   <-----Delete this line
pattern3
adsffdsd
huaserew

Please can you suggest how this can be done using awk or sed or in perl.

+5
source share
5 answers
sed '/pattern1/,${ /pattern2/,/pattern3/{/pattern2/b; /pattern3/b; d;} };' file

formatted:

/pattern1/,$ {
    /pattern2/,/pattern3/ {
        /pattern2/b;
        /pattern3/b; 
        d;
    } 
}

Explanations:

  • /pattern1/,$is the range of lines after pattern1to the end of the file
  • /pattern2/,/pattern3/- range of lines between pattern2andpattern3
  • /pattern2/b;and /pattern3/b;skip lines pattern2and pattern3that are otherwise included in the range (see sed faq )
  • d deletes other rows in a range

Update

From the comments, the internal block can be rewritten:

//!d

Where:

  • // ( ) ( pattern2 pattern3
  • ! , , ,
  • d

, , :

/pattern1/,$ {
    /pattern2/,/pattern3/ {
        //!d
    } 
}
+4

awk :

awk '
    BEGIN {print_line = 1}
    /pattern1/ {consider = 1}
    consider && /pattern2/ {print_line = 0; print}
    consider && /pattern3/ {print_line = 1}
    print_line {print}
' filename
+3

perl, flip-flop. , - , pattern1 pattern2:

  • pattern1 pattern2, pattern3 pattern1 Pattern3

  • , pattern1 pattern2, pattern3 , pattern1. > .

, perl -p

-n                assume "while (<>) { ... }" loop around program
-p                assume loop like -n but print line also, like sed

, , ..

perl -pe'$x ||= /7/; $_= "" if /5/ .. /8/ and $x' <(seq 1 10)
1
2
3
4
5
6
9
10

$x ||= /7/: $x /7/, $x false. /7/ true, . , $x true, ||= , .

$_ = '', /5/ /8/, $x true. , : a && b run b, a true. a -- - , ; , , $_ = '' , 7.

, quesiton ...

perl -pe'$x ||= /7/; $_= "" if $x and /5/ .. /8/' <(seq 1 10)

. Perl /5/, /7/. .

, , ...

perl -pe'$x||=/2/;$_=""if$x&&/5/../8/' # secksey
+2

:

perl -ne '++$saw_pattern1 if /pattern1/;
          $inside = ($saw_pattern1 && /pattern2/) .. /pattern3/;
          print unless $inside && ($inside > 1 && $inside !~ /E0$/)' \
  input

Perls .. .

.. . , , () sed, awk . .. , . , . , , , . , ...

, , , . || &&. false, ( 1) true. reset . E0, , - , . , , 1.

+1

:

sed '/pattern1/,$!b;/pattern2/,/pattern3/!b;//!d' file
+1

All Articles