Ligne précédente d'un texte [Résolu/Fermé]

Signaler
-
 Luluu -
Bonjour, je débute en perl, comment désigner simplement la ligne précédente dans un fichier txt sans utiliser de tableau ? En fait pour chaque expression trouvée dans une ligne, je dois afficher une information se trouvant dans la ligne au-dessus. Merci de vos réponses.



3 réponses

Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
Bonjour Luluu,

A quoi ressemble ton code ?

Ce qui me vient à l'esprit, a priori, est que dans ta boucle, tu sauvegardes le contenu de la ligne précédente dans une variable avant la fin de ta boucle, pour en disposer lorsque tu traites la nouvelle ligne.


Dal
Merci de ta réponse. Voici mon code (il est tout bête):

while (my $ligne = <STDIN>) {
chomp $ligne ;
while ($ligne =~ /expression à extraire/ig) {
print $&, " " ;
}
if ($ligne =~ /^<ARTICLEréférence(date)référence>$/) {
print "(", $1, ")\n" ;
}
} # (Entrer dans le terminal: "perl -CIO [chemin du programme] < [chemin du corpus] | sort -u".)

Ça m'affiche la date de chaque article de mon fichier, même de ceux qui ne contiennent pas l'expression que je veux extraire ; or je veux uniquement extraire une (ou des) expression(s) et indiquer la date de l'article dans lequel elle-s se trouve-nt (information qui se trouve donc dans la ligne précédente, puisque chaque article est sur une seule ligne et la réf de l'article avec la date est sur la ligne au-dessus).
À partir de ce que tu m'as dit, j'ai commencé à mettre ma boucle if en premier et à sauver la date dans une variable, mais même avec ça je ne vois pas après comment articuler ma requête (en plus ma maîtrise des variables n'est pas optimale...). Ou sinon, comment éliminer les résultats qui contiennent seulement une date... (j'aimerais éviter d'avoir à retraiter ce que j'obtiens en sortie de ce code via le terminal ou un second programme)
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
OK, une solution pourrait être d'utiliser le modificateur s ("Treat string as single line") avec une seule regexp pour matcher tous les éléments. Pour cela, il faut pouvoir les distinguer dans leur structure. Peux-tu donner un exemple représentatif des lignes que tu traites, en indiquant ce que tu veux extraire sur ces lignes

Dal
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
Voilà un exemple, à appliquer à ton cas :

#!/usr/bin/perl

use strict;
use warnings;

# exemple ci-dessous avec un contenu affecté dans le code
# pour des données passées par STDIN, faire un slurp de STDIN
# dans une chaîne $st, comme ceci :
# my $st = do { local $/; <STDIN> };

my $st=q(
<ARTICLEréférence(06-11-2015)référence>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque porta mauris eleifend, rutrum tortor sit amet, accumsan dolor. Nam in varius urna. expression1 à extraire Proin orci orci, bibendum eget diam sit amet, luctus sodales elit. In turpis nibh, rhoncus eget eros ut, facilisis laoreet ipsum.

<ARTICLEréférence(22-11-2015)référence>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque porta mauris eleifend, rutrum tortor sit amet, accumsan dolor. Nam in varius urna. expression2 à extraire Proin orci orci, bibendum eget diam sit amet, luctus sodales elit. In turpis nibh, rhoncus eget eros ut, facilisis laoreet ipsum.
);

print "date : $1 - extrait : $2\n"
    while $st =~ /<ARTICLE.*?(\d\d-\d\d-\d{4}).*?(express.*?à.*?ire)/sg;


donne :

date : 06-11-2015 - extrait : expression1 à extraire
date : 22-11-2015 - extrait : expression2 à extraire

Dal
Merci de ton aide, mes lignes ressemblent tout à fait à ce que tu as mis dans ta dernière réponse, mais n'étant pas familière du modificateur s, je me suis finalement basée sur ta 1ère réponse pour écrire ce code qui convient bien :

my $date ;
while (my $ligne = <STDIN>) {
	chomp $ligne ;
	if ($ligne =~ /^<A.*\pL+-(\d+)-\pL+.*$/) {
		$date = $1 ;
	}
	if ($ligne =~ /\d+((,|.| )\d+((.| )\d+)?)?( milli(on|ard)s? de)? mots/i) {
		while ($ligne =~ /\d+((,|.| )\d+((.| )\d+)?)?( milli(on|ard)s? de)? mots/ig) {
			print $&, " ; " ;
		}
		print "(", $date, ")\n" ;
	}
}


J'obtiens ce genre de résultat :
134.445 mots ; 26.000 mots ; (2012)
40 mots ; (2012)
1 457 mots ; (2013)
109 689 mots ; 120 378 mots ; (2013)
1,6 milliard de mots ; 47 mots ; 47 mots ; 57 mots ; 47 mots ; 47 mots ; 20 mots ; (2013)

Je tenais notamment à ce que les expressions d'un même article soient affichées sur la même ligne.
Je vais cependant explorer ton autre proposition ; je devais écrire ce programme dans le cadre d'exercices d'apprentissage du perl et je préférais m'en tenir à ce que nous avions déjà vu en cours, je bloquais juste sur l'articulation des boucles et des variables ^^'... Mais ça ne m'empêche pas d'aller plus loin avec ce que tu m'as dit :).
Encore merci, bon dimanche :)