Enlever des sauts de ligne de manière sélective

Fermé
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - 18 avril 2013 à 17:51
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 - 21 avril 2013 à 22:59
Salut, (je suis sous ubuntu 12.04)

J'ai un beau fichier tout bien parsé mais j'aimerai réduire le nombre de lignes en enlevant certains sauts de ligne de manière sélective.

J'explique :
Dans ce fichier, pour l'instant en deux colonnes dont le séparateur est le point-virgule (je n'utilise pas la virgule car elle sert dans certains champs !), j'ai des variables dans la 1ère colonne, et leurs valeurs dans la seconde.

J'ai 5 variables différentes qui se répètent (observations d'animaux) plus ou moins régulièrement. Tout d'abord, à chaque nouvelle espèce, il y a ces trois lignes (Espèce, Nb_Obs, ID_esp) :
Espèce; Crocodile d'Afrique - warn.
N_Obs; 3 observations 
ID_esp; 87


Puis, il y a ces trois variables qui se suivent toujours entre elles (Lieu, Observateur, Date), mais le bloc se répète N fois, où N correspond au nombre d'observations ci-dessus (3 ici) :
Lieu; Parc National
Observateur; Smith P.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Wilson, Jr.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Smith P.
Date; 17.04.2013



Puis ça passe à l'espèce suivante.

1. Je souhaite pour plus de clarté (enfin j'espère...), arriver à cela (intermédiaire) :
Espèce; Crocodile d'Afrique - warn.; Nb_Obs; 3; ID_esp; 87;
Date; 18.04.2013; Lieu; Parc National; Observateur; Smith P.
Date; 18.04.2013; Lieu; Parc Intérieur; Observateur; Wilson, Jr
Date; 17.04.2013; Lieu; Parc Intérieur; Observateur; Smith P.


Puis l'espèce suivante... etc.
Donc enlever les sauts de ligne qui correspondent au passage de la ligne contenant la variable Lieu à celle contenant Observateur, puis le saut de la ligne contenant Observateur à celle contenant Date afin de regrouper ces trois variable en une seule ligne.
Idem avec les variables précédentes : Espèce -> Nb_Obs et Nb_Obs -> ID_esp


Et je pose ici mon idée suivante :
---------------------------
2. Et au final, mais je me tâte encore de savoir si c'est mieux ou pas ; avoir une ligne par observation :
Espèce; Crocodile d'Afrique - warn.; Nb_Obs; 3; ID_esp.; 87; Date; 18.04.2013; Lieu; Parc National; Observateur; Smith P.
Espèce; Crocodile d'Afrique - warn.; Nb_Obs; 3; ID_esp.; 87; Date; 18.04.2013; Lieu; Parc Intérieur; Observateur; Wilson, Jr;
Espèce; Crocodile d'Afrique - warn.; Nb_Obs; 3;ID_esp.; 87; Date; 17.04.2013; Lieu; Parc Intérieur; Observateur; Smith P.


Et mieux encore, mettre ça sous forme de colonnes (réarrangées) pour pouvoir aller chercher rapidement et facilement l'information quand on en aura besoin plus tard (par exemple avec un grep (en espérant pouvoir retrouver comment faire un "uniq" sur un champ précis) pour trouver tous les éléphants vus le 17.04.2013 à tel endroit) :
Espèce ; ID_esp ; Nb_Obs; Date; Lieu; Observateur;
Crocodile d'Afrique - warn. ; 87; 3; 18.04.2013; Parc National; Smith P.
Crocodile d'Afrique - warn. ; 87; 3; 18.04.2013; Parc Intérieur; Wilson, Jr.
Crocodile d'Afrique - warn. ; 87; 3; 17.04.2013; Parc National; Smith P.


Etc.

Nota : Peut-être est-il plus simple de tout de suite arriver à l'étape finale ? Si oui tant mieux. Mon esprit ne prend pas forcément les chemins qui seraient logiques à un ordinateur...


Je sais que je ne couperai pas à awk sur ce coup mais j'ai déjà tout oublié :( c'est affreux.

Merci !
J'espère avoir été suffisamment clair.


3 réponses

dubcek Messages postés 18718 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 22 mars 2024 5 615
19 avril 2013 à 13:16
hello
j'ai gardé l'ordre des champs du fichier:
$ awk -f f1.awk a1
Espèce ; N_Obs ; ID_esp ; Lieu ; Observateur ; Date
 Crocodile d'Afrique - warn. ; 3 ; 87 ;  Parc National ; Smith P.; 18.04.2013
 Crocodile d'Afrique - warn. ; 3 ; 87 ;  Parc Intérieur ; Wilson, Jr.; 18.04.2013
 Crocodile d'Afrique - warn. ; 3 ; 87 ;  Parc Intérieur ; Smith P.; 17.04.2013
$ 
$ cat a1
Espèce; Crocodile d'Afrique - warn.
N_Obs; 3 observations 
ID_esp; 87
Lieu; Parc National
Observateur; Smith P.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Wilson, Jr.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Smith P.
Date; 17.04.2013
$ cat f1.awk
BEGIN{FS=OFS=";"; print "Espèce ; N_Obs ; ID_esp ; Lieu ; Observateur ; Date"}
/^Espèce/  {e=$2}
/^N_Obs/ {split($2, t, "[ ]*"); n=t[2]}
/^ID_esp/ {id=$2}
/^Lieu/ {printf "%s ; %d ; %d ; %s ;", e, n, id, $2}
/^Observateur/ {printf $2}
/^Date/ {print $2 OFS}
$ 
1
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
18 avril 2013 à 18:53
Salut,

Je n'ai pas la solution finale, je n'ai que la "1", mais c'est déjà ça ;-)

C'est avec "sed". Par contre il doit y avoir la possibilité avec "awk" ou "perl" de faire ce que tu veux en une seule fois. Je laisse le soin aux adeptes comme "dubcek" de nous en faire la démonstration ;-))

J'ai rajouté des lignes pour que l'exemple soit plus parlant...

Le contenu du fichier :
$ cat brol
Espèce; Crocodile d'Afrique - warn.
N_Obs; 3 observations 
ID_esp; 87
Lieu; Parc National
Observateur; Smith P.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Wilson, Jr.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Smith P.
Date; 17.04.2013
Espèce; Éléphant d'Afrique - warn.
N_Obs; 4 observations 
ID_esp; 87
Lieu; Parc National
Observateur; Smith P.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Wilson, Jr.
Date; 18.04.2013
Lieu; Parc Intérieur
Observateur; Smith P.
Date; 17.04.2013
Lieu; Parc Intérieur
Observateur; Doe J.
Date; 16.04.2013

Le script pour sed :
$ cat script.sed 
#n
:esp
/^Espèce/{
N
N
s/\n/ /g
p
d
}

/^Espèce/!{
/^Date/!{
h
n
H
n
G
s/\n/ /g
p
d
}
}
$ b
/^Espèce/ b esp

L'exécution :
$ sed -f script.sed brol 
Espèce; Crocodile d'Afrique - warn. N_Obs; 3 observations  ID_esp; 87
Date; 18.04.2013 Lieu; Parc National Observateur; Smith P.
Date; 18.04.2013 Lieu; Parc Intérieur Observateur; Wilson, Jr.
Date; 17.04.2013 Lieu; Parc Intérieur Observateur; Smith P.
Espèce; Éléphant d'Afrique - warn. N_Obs; 4 observations  ID_esp; 87
Date; 18.04.2013 Lieu; Parc National Observateur; Smith P.
Date; 18.04.2013 Lieu; Parc Intérieur Observateur; Wilson, Jr.
Date; 17.04.2013 Lieu; Parc Intérieur Observateur; Smith P.
Date; 16.04.2013 Lieu; Parc Intérieur Observateur; Doe J.

$

0
Swiss Knight Messages postés 1956 Date d'inscription samedi 22 novembre 2008 Statut Membre Dernière intervention 27 juillet 2016 110
21 avril 2013 à 22:59
Salut par ici,
Je n'ai encore pas testé ta solution zipe, donc je commente celle de dubcek ici, dont je rappelle le code :
BEGIN{FS=OFS=";"; print "Espèce ; N_Obs ; ID_esp ; Lieu ; Observateur ; Date"}
/^Espèce/  {e=$2}
/^N_Obs/ {split($2, t, "[ ]*"); n=t[2]}
/^ID_esp/ {id=$2}
/^Lieu/ {printf "%s ; %d ; %d ; %s ;", e, n, id, $2}
/^Observateur/ {printf $2}
/^Date/ {print $2 OFS}


Alors avant toute chose : un tout grand merci !
Ça marche du tonnerre, ou presque (d'ailleurs merci d'y avoir laissé quelques coquilles ; ça m'a permis de "débuger" et donc de chercher des infos pour y arriver et c'est toujours très intéressant ça. Bien plus que de partir de zéro !) :

- Mon séparateur n'était en fait pas ";" mais "; " (point-virgule suivi d'une espace) : donc en changeant : FS=OFS="; " ça marche nickel.

- Le split fait appel à la deuxième partie du champ "splité", alors que c'est dans la 1ère partie que le nombre d'observations est présent ---> n=t[1] fonctionne à merveille !

- J'ai dû changé les deux dernières lignes en ceci :
/^Observateur/ {printf " " $2 " " OFS}
/^Date/ {print $2}

pour d'une part mettre un séparateur entre l'avant-dernier et le dernier champ (il n'y en avait pas avant), et d'autre part rajouter deux espaces autour du champ $2 pour être consistant avec le reste du fichier (il était collé aux point-virgules qui l'entourent sinon. Remarque ; on peut aussi faire ça en rajoutant une espace après le dernier présent entre les guillemets du printf de la ligne du lieu !).
J'espère avoir fait ça correctement ? Dans les fait ça marche bien en tout cas.

Voilà, j'essaye ton code dès que j'ai un moment cette semaine zipe, histoire d'atteindre l'étape intermédiaire correctement aussi. Je passerai faire un petit topo aussi ;)

Merci à vous en tout cas !
Bonne nuit et commencez bien la semaine !

0