Script awk: comment fusionner des lignes?

Résolu/Fermé
awkgirl - 7 mars 2008 à 18:39
 Florent - 12 déc. 2012 à 11:56
Bonjour,


je dispose d'un corpus anglais et français proposant des lignes (src), soit source, en alternance avec des lignes (trg), soit cible. Le problème est que parfois 2 (ou plus) phrases (src) se suivent pour une seule correspondance (trg), ou, à l'inverse: 2 (ou plus) phrases (trg) se suivent pour une seule phrase (src)

Exemple:

25 (src)="s8.1"> If the spin box defines numerical values , you can
also define a measurement unit , e.g. , 1 cm or 5 mm , 12 pt or 2 " .
26 (trg)="s8.1"> Lorsque vous saisissez une valeur numérique , vous
pouvez aussi spécifier une unité de mesure , par ex .
27 (trg)="s8.2"> 1 cm , 5 mm , 12 pt ou 2 " ( pour 2 pouces ) .
28 (src)="s9.1"> Convert
29 (trg)="s9.1"> Convertir.

Je souhaite donc regrouper les (src) et les (trg) qui se suivent afin de disposer d'un corpus correctement aligné.

Au pire, j'ai un script à renouveler plusieurs fois:


my $file = $ARGV[0];
my $nextline;
open(IN, "< $file") || die "Couldn't open file!";

while(<IN>){
if($_=~m/^\(trg\)="s[0-9]+\.[0-9]+">/){
$nextline=<IN>;
if($nextline=~m/^\(trg\)="s[0-9]+\.[0-9]+">/){
$nextline=~s/\(trg\)="s[0-9]+\.[0-9]+">//;
$_=~s/\n//;
print $_;
print $nextline;
}
else{
print $_;
print $nextline;
}
}
else{
print $_;
}

}

close(IN);

Mais comme je débute, je n'arrive pas à écrire un script awk qui me permettrait de fusionner ces lignes en une seule fois. D'autant que je dois réunir 1000 couples de phrases, et je me vois mal valider mon script 1000 fois au pire des cas... ;-)

Merci beaucoup pour votre aide!
A voir également:

11 réponses

Une façon très simple sous awk de grouper des lignes sur une seule ligne est d'utiliser la variable RS (record separator) qui défini la fin d'une ligne.

Normalement égal à \n il suffit de l'ajouter dans l'entête du script pour regrouper les lignes voulues ensemble.

Exemple : sortir les paragraphes d'un fichier html
awk 'BEGIN {RS="</?p>"}{print $0}' page.htm

reste encore à les mettre sur une ligne, ce que les instructions sur les $i de awk permettent par ailleurs.


Voir aussi :
- FS, équivalent pour les champs
- regex1, regex2 qui défini un intervalle de champs ou lignes subissant le même traitement
1
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
8 mars 2008 à 10:39
Salut,

T'es sûre que c'est pas du "Perl" plutôt ton script ?

Tu peux nous afficher davantage de lignes de ton fichier, ou même mieux, le mettre sur Cjoint ;-))
0
Salut jipicy!

Merci beaucoup de t'être soucié de mon problème!!

Figure-toi que mon prof vient de nous envoyer un mail disant qu'il était lui-même incapable de faire fusionner des lignes en une seule fois. Je crois donc que cette question sera à jamais irrésolue!
En outre, je ne dispose pas du corpus aujourd'hui car il est sur un serveur qui m'est inaccessible ce week-end!
La suite, lundi matin donc!

Un bon week-end à toi!
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
10 mars 2008 à 14:11
Le serveur est down ? ;-))
0
Salut jispicy!

j'étais tellement occupée ce matin à essayer de résoudre tous ces problèmes épineux que (honte sur moi) je n'ai pas pris le temps de t'en dire plus.
En fait quelqu'un m'a donné unscript qui permet bien de fusionner des lignes:

#! /usr/bin/awk -f
# cleanOO-align.awk
# nettoie

BEGIN {src = 0; trg = 0}
{if ($1 == "====================")#if line starts with +++, copy the whole line. Set src and trg to 0
{
src = 0;
trg = 0;
print $0;
next;
}
}
{if (index($0,"(src)") != 0) #if line starts with (src), check if already exists src, if no, copy whole line, if yes copy just text
{
src++;
if (src > 1)
{
print substr($0, length($1) + 1, length($0))
}
else
{
print $0
};
next;
}
}
{if (index($0, "(trg)") != 0)#if line starts with (trg), check if already exists src, if no, copy whole line, if yes copy just text
{
trg++;
if (trg > 1)
{
print substr($0, length($1) + 1, length($0))
}
else
{
print $0
};
next;
}
}




Le nouveau problème maintenant: il faut supprimer les retours à la ligne engendrés par ce script qui "ne colle pas" les 2èmes phrases aux premières, tu me suis?

En outre j'ajoute qu'on a dû aussi faire des manips à la main pour supprimer des orphelins (des src ou trg seuls), et c'est ça que ne savait pas faire mon prof.

Aurais-tu une petite idée pour supprimer ces retours à la ligne?

Je sais, j'exagère, mais on ne nous a pas appris à écrire de scripts comme celui-là!
La paradoxe est fort! (Molière) ;-)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
10 mars 2008 à 14:48
Euh...j'ai peut être une solution mais avec "sed" et non "awk", c'est grave ?

Et le fichier, je peux en avoir un plus gros extrait ???

;-)
0
Pas de problème avec sed, de toute façon, au point où j'en suis!

Voici mon fichier: https://www.cjoint.com/?dkoYYFN7R3

Merci infiniment jipicy!!
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
10 mars 2008 à 15:07
[tmpfs]$ sed '/^(trg)/{N;/\n==*/! s/\n//}' OO-enfr-E_ENFR-v3.txt > temp.txt
[tmpfs]$ sed '/^(src/{N;/\n(trg)/! s/\n//}' temp.txt > final.txt
;-))
0
Alors là un grand merci et un grand bravo! Ca marche!!

Une dernière petite question: à quoi correspond le N?

Promis, après, je ne t'embête plus (enfin j'espère).

;-)
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
10 mars 2008 à 15:44
Tiens voilà le script dans un fichier et qui traite tout d'un coup, avec commentaires :
/^(src)/{               # Si la ligne commencent par
N                       # Ajouter la ligne suivante dans l'espace de travail
/\n(trg)/{              # Si le caractère saut de ligne (\n) est suivi de "(trg)
P                       # Afficher la 1ère partie de l'espace de travail (jusqu'au saut de ligne)
D                       # Effacer la 1ère partie de l'espace de travail (jusqu'au saut de ligne)
b trg                   # Et se brancher à l'étiquette "trg"
}
/\n(src)/!{              # Si le caractère saut de ligne (\n) n'est pas suivi de "(src)"
s/\n//                  # supprimer le caractère saut de ligne (\n)
}
}

:trg                    # Étiquette
/^(trg)/{               # Si la ligne commencent par
N                       # Ajouter la ligne suivante dans l'espace de travail
/\n==*/!{                # Si le caractère saut de ligne (\n) n'est pas suivi par des "="
s/\n//                  # supprimer le caractère saut de ligne (\n)
}
}

Donc à enregistrer dans un fichier (par exemple "script.sed") et à appeler de cette façon :
sed -f script.sed OO-enfr-E_ENFR-v3.txt > final.txt
Si tu as une version de "sed" supérieure à 4.0.5, tu peux éditer directement le fichier original (en faisant une sauvegarde toutefois) de cette façon :
sed -f script.sed -i.BAK OO-enfr-E_ENFR-v3.txt
;-))
0
Alors là!!!

Je ne sais pas comment te remercier!

Toutes ces précisions si claires!

J'ai fini ma tâche pour aujourd'hui, mais il se peut très bien que je fasse encore appel à toi dans les jours à venir!

Encore merci pour ta patience et bravo pour ta pédagogie!
0
jipicy Messages postés 40842 Date d'inscription jeudi 28 août 2003 Statut Modérateur Dernière intervention 10 août 2020 4 897
10 mars 2008 à 17:39
De rien ;-))
0