J'ai un fichier dont le contenu est le suivant:
zdk
aaa
b12
cdn
dke
kdn
Input1: aaa
et cdn
Sortie 1:
aaa
b12
cdn
Entrée 2: zdk
et dke
Sortie 2:
zdk
aaa
b12
cdn
dke
Je pourrais utiliser les commandes ci-dessous pour réaliser:
grep -a aaa -A2 file # Output 1
grep -a aaa -A4 file # Output 2
Mais dans le fichier, je ne sais pas quelle est l'occurrence (position) exacte du modèle de chaîne de fin (le fichier contient 20000 lignes)
Comment puis-je atteindre cet objectif?
grep
ne vous aidera pas ici. C'est un travail mieux accompli avec sed
en utilisant des expressions de plage:
$ sed -n '/aaa/,/cdn/p' file
aaa
b12
cdn
$ sed -n '/zdk/,/dke/p' file
zdk
aaa
b12
cdn
dke
sed -n
supprime l'impression automatique, afin que les lignes soient imprimées juste si cela est explicitement demandé. Et cela se produit lorsque la plage /aaa/,/cdn/
arrive.
Ces expressions de plage sont également disponibles dans awk
, où vous pouvez dire:
awk '/zdk/,/dke/' file
Bien sûr, toutes ces conditions peuvent être étendues à une expression rationnelle plus stricte comme sed -n '/^aaa$/,/^cdn$/p' file
pour vérifier que les lignes se composent exactement de aaa
et cdn
, rien d'autre.
Cela peut être fait par sed
sed -n '
/^aaa$/,/^cdn$/w output1
/^zdk$/,/^dke$/w output2
' file
Voici la commande grep
:
grep -o "aaa.*cdn" <(paste -sd_ file) | tr '_' '\n'
Vous pouvez obtenir une correspondance multiligne dans grep
, mais vous devez utiliser Perl-regexp pour grep
(-P
- qui n'est pas pris en charge sur toutes les plates-formes, comme OS X), donc comme solution de contournement, nous remplaçons les nouvelles lignes par _
caractère et après grep
, nous les modifions en arrière.
Vous pouvez également utiliser pcregrep
qui prend en charge les modèles à plusieurs lignes (-M
).
Ou utilisez ex
:
ex +"/aaa/,/cdn/p" -scq! file