Imprimer la ligne après la nième occurrence d'une correspondance


8

Je cherche à afficher la ligne 4598 dans le fichier suivant. En fait, je veux afficher la ligne APRÈS la nième occurrence d'une correspondance. Dans ce cas, la ligne après la 3ème occurrence de <Car>. Comment dois-je procéder?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>

1
Bien qu'il soit possible d'obtenir ce que vous souhaitez utiliser sed, awkou même grep, il est conseillé d'utiliser un analyseur XML.
devnull

XML n'a été utilisé que pour l'exemple, le texte peut être de n'importe quel format
DJ180

Réponses:


10
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'

Ou:

awk '/<Car>/ && ++n == 3 {getline; print; exit}'

Pour passer le modèle de recherche en tant que variable:

var='<car>'
PATTERN="$var" awk -v n=3 '
  $0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'

Ici, l'utilisation ENVIRONau lieu de -vas -vdéveloppe les séquences d'échappement antislash et les antislashs sont souvent trouvés dans les expressions régulières (il faudrait donc les doubler -v).

GNU awk4.2 ou supérieur vous permet d'affecter des variables en tant que regexps typés forts . Tant que son mode POSIX n'est pas activé (par exemple via la $POSIXLY_CORRECTvariable d'environnement, vous pouvez faire:

# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
  $0 ~ pattern && ++n == 3 {getline; print; exit}'

Comment passer le modèle de recherche également comme variable dans la commande ci-dessus
WanderingMind

@WanderingMind, voir modifier.
Stéphane Chazelas

4

En voici un:

perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file 

Avec GNU grep, vous pouvez également analyser sa sortie comme:

grep -A 1 -m 3 '<Car>' file | tail -n 1

De man grep:

-A NUM, --after-context=NUM
          Print NUM lines of trailing context after matching lines.  
          Places a line containing a group separator (--) between 
          contiguous  groups  of  matches.          
-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  

3

Avec GNU awkvous pouvez faire:

gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile

1

Voici une autre façon avec sed:

sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile

Cela utilise l'espace d'attente pour compter.
Chaque fois qu'il rencontre une ligne correspondant, <Car>il xchange de tampon et vérifie s'il y a exactement N-1 occurrences d'un caractère dans le tampon de maintien. Si la vérification réussit, elle xchange à nouveau, et si elle n'est pas sur la dernière ligne, elle tire sur la nligne ext et pimprime l'espace de motif puis se qferme. Sinon, cela ajoute simplement un autre caractère .à l'espace d'attente et e xchange de nouveau.


0

Voici une solution de ligne de commande simple.

grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1

Si vous modifiez la valeur de +3 après tail, vous pouvez spécifier n'importe quelle nième ligne.


Vous ne savez pas pourquoi vous avez ajouté les balises, sed, awk, etc. Si vous voulez une solution utilisant une application spécifique, un utilitaire, vous devez le spécifier en question ou en titre.
bsd
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.