grep
n'est pas bien adapté à cette tâche, vous devez monter d'un outil :
sed -n '/^B/,/^E/p' infile
Sortie :
B
C
D
E
B
C
E
En ce qui concerne la nième exigence, je pense que c'est plus facile si vous avancez à nouveau un outil "vers le haut", à savoir awk :
awk '/^B/ { f = 1; n++ } f && n == wanted; /^E/ { f = 0 }' wanted=2 infile
Sortie :
B
C
E
Le drapeau f
sera défini lorsque /^B/
est rencontré et non défini lorsque /^E/
se produit, de la même manière que la notation sed fonctionne. n
garde un décompte du nombre de blocs passés et quand f == 1 && n == wanted
est vrai, le bloc par défaut sera exécuté ({ print $0 }
).
Le sed
de @Thor la commande ne peut pas être battue, mais avec le perl
suivant script J'essaie de répondre à la partie de votre question entre parenthèses :"... la (Nième) occurrence...".
Utilisation :
./script <start-regex> <end-regex> [N]
Exemples avec le fichier dans votre question :
$ ./script "B" "E" < examplefile
B
C
D
E
B
C
E
$ ./script "B" "E" 2 < examplefile
B
C
D
E
F
G
B
C
E
Il n'y a pas de vérification d'erreur ou quoi que ce soit et le script est non gourmand, c'est-à-dire à partir de A B C D E E F
seulement B C D E
sera greffé avec N=1.
#!/usr/bin/perl
if ($ARGV[2] != "") { $n = $ARGV[2] } else { $n = 1 }
$begin_str = $ARGV[0];
$end_str = $ARGV[1];
while(<STDIN>) {
if($_ =~ $begin_str) { $flag=1 } # beginning of match, set flag
if($_ =~ $end_str && $flag eq 1) { $i++ } # i-th occurence of end string
if($i eq $n) { # end of match after n occurences of end string
$flag=2;
$i=0;
}
if ($flag ge 1) { # append currrent line to matching part
$out.=$_;
}
if($flag eq 2) { # after detection of end of match, print complete match
print $out;
# print "---\n"; # separator after a match
$out="";
$flag=0;
}
}