OVH Cloud OVH Cloud

selectionner les lignes d'un fichier contenant des maximums

33 réponses
Avatar
geo cherchetout
Bonjour,
J'ai un fichier texte dont chaque ligne contient, après un premier
nombre et une espace, un second nombre compris entre 0 et 1. En voici un
extrait :

0.0023129252 0.68157959
0.0023356009 0.68902588
0.0023582766 0.71615601
0.0023809524 0.72515869 <--
0.0024036281 0.71878052
0.0024263039 0.72677612 <==
0.0024489796 0.71615601
0.0024716553 0.70773315
0.0024943311 0.68917847

Ce second nombre représentant lui-même des échantillons d'une onde
sonore de composition spectrale très pauvre, passe toutes les 50 à 200
lignes par un vrai maximum comme celui de la ligne 6. Deux maximums
successifs sont séparés par un minimum dont la valeur est au moins 10
fois plus faible, ce qui permet de les distinguer de quelques faux
maximums comme celui de la ligne 4.
Je voudrais écrire un script dont l'exécution réduise ce fichier aux
seules lignes contenant ces vrais maximums. Quelles commandes ou quel
langage de programmation, et donc quelles pages de manuel me conseillez
vous, sachant que mes connaissances sont des plus modestes ?
Merci d'avance.

10 réponses

1 2 3 4
Avatar
Stephane Chazelas
2004-11-25, 18:38(+01), geo cherchetout:
Le 25.11.2004 17:07, *Stephane Chazelas* a écrit fort à propos :

Peux-tu donner un exemple d'un maximum (avec son contexte) qui
aurait du etre affiché ?


J'ai déposé un fichier test de 5000 lignes ici :
http://cjoint.com/?lyx0aSrYhm

Et voici un exemple de ligne qui aurait du être conservée, avec un
certain nombre avant et après pour montrer qu'il s'agit bien d'un
maximum précédé et suivi de minimums conformes :

0.0018367347 0.038726807
0.0018594104 0.0036621094 (mini)
0.0018820862 0.020843506
[...]

0.0023356009 0.68902588
0.0023582766 0.71615601
0.0023809524 0.72515869 (faux maxi)
0.0024036281 0.71878052
0.0024263039 0.72677612 (maxi)
0.0024489796 0.71615601
[...]

0.0031292517 0.0047912598 (mini)



Parle-t-on bien du meme script:

#! /usr/bin/awk -f
# Usage: script.awk < fichier.in > fichier.out
$2 > max && $2 > 10 * min {
max = $2
ligne = $0
next
}
10 * $2 < max {
print ligne
max = 0
min = $2
}
END {
if (max) print ligne
}

Parce que dans l'exemple ci-dessus, il me sort (avec gawk 3.14):

0.0018367347 0.038726807
0.0024263039 0.72677612 (maxi)

Et avec l'exemple de 5000 lignes, il me sort 122 lignes, dont:

0 0.030883789
0.0014739229 0.33233643
0.0024263039 0.72677612
0.0036054422 0.76242065
0.0060090703 0.82589722
0.0072335601 0.802948
0.0084580499 0.8883667
0.011972789 0.85714722
0.013038549 0.86816406
0.014126984 0.79888916


--
Stephane


Avatar
geo cherchetout
Le 25.11.2004 18:51, *Stephane Chazelas* a écrit fort à propos :

Parle-t-on bien du meme script:

#! /usr/bin/awk -f
# Usage: script.awk < fichier.in > fichier.out
$2 > max && $2 > 10 * min {
max = $2
ligne = $0
next
}
10 * $2 < max {
print ligne
max = 0
min = $2
}
END {
if (max) print ligne
}


Oui, j'ai simplement copié/collé ce texte pour l'écrire.

Et avec l'exemple de 5000 lignes, il me sort 122 lignes, dont:

0 0.030883789
0.0014739229 0.33233643
0.0024263039 0.72677612
0.0036054422 0.76242065


Superbe ! En comptant de visu les crêtes du signal avec Audacity, je
crois que j'avais trouvé 120. J'ai très bien pu en rater une, ce qui
nous mettrait à égalité en éliminant ta première ligne.

Je vais voir si je peux upgrader mon gawk.

Avatar
Jérémy JUST
On Thu, 25 Nov 2004 11:05:10 +0000
Stephane Chazelas wrote:

Il existe a2p pour convertir un programme awk en perl.


Mon code est quand même plus lisible! ;)


$[ = 1; # set array base to 1


C'est c'lâââ, oui.


$ = "n"; # set output record separator
[...]
chomp; # strip record separator


Pfff, il suffit de ne pas le retirer en entrer pour ne pas avoir à le
remettre en sortie.


@Fld = split(' ', $_, 9999);


C'est moche et coûteux. Je me suis demandé un instant si ça ne
risquait pas de poser des problèmes, mais je ne crois pas.

--
Jérémy JUST

Avatar
geo cherchetout
Le 25.11.2004 21:14, j'écrivais :

Je vais voir si je peux upgrader mon gawk.


Bof ! Avec gawk-3.1.4, je suis passé d'une extrémité à l'autre.
J'obtiens à présent 1768 lignes sur 5000.

Il faut dire que j'ai emprunté le gawk-3.1.4-4.i386.rpm pour la
distribution "Fedora Core Development for i386". C'est peut-être pas
très orthodoxe ?

Avatar
geo cherchetout
Le 25.11.2004 17:07, *Stephane Chazelas* a écrit fort à propos :

Essaie peut-etre gawk ou nawk a la place de awk.


J'ai installé mawk (avec un m comme Maman) et ton script a fonctionné du
premier coup, avec le même résultat que gawk-3.1.4 chez toi.
Maintenant, il me reste à comprendre tranquillement pourquoi ça marche,
et ce sera sûrement le plus difficile.
Je reste bien sûr disponible pour toute expérimentation ou investigation
avec gawk-3.1.3 et gawk-3.1.4, dans la mesure de mes faibles connaissances.
Bien cordial salut et merci à tous.

Avatar
Jérémy JUST
On Thu, 25 Nov 2004 22:11:35 +0100
geo cherchetout wrote:

Bof ! Avec gawk-3.1.4, je suis passé d'une extrémité à l'autre.


C'est un peu surprenant que les résultats d'un script aussi simple
changent du tout au tout suivant la version de awk. Je pensais que
c'était un langage relativement normalisé (au moins pour les
fonctionnalités de base).

--
Jérémy JUST

Avatar
Stephane Chazelas
2004-11-25, 23:35(+01), Jérémy JUST:
On Thu, 25 Nov 2004 22:11:35 +0100
geo cherchetout wrote:

Bof ! Avec gawk-3.1.4, je suis passé d'une extrémité à l'autre.


C'est un peu surprenant que les résultats d'un script aussi simple
changent du tout au tout suivant la version de awk. Je pensais que
c'était un langage relativement normalisé (au moins pour les
fonctionnalités de base).


Ok, probleme identifié.

C'etait le LC_NUMERIC a fr_FR qui posait probleme. En France, le
point decimal est une virgule, donc gawk prenait "0.123123" pour
"0" (il attend 0,123123).

$ echo 0.123 | LC_NUMERIC=fr_FR gawk '{print $1 + 0}'
0
$ echo 0.123 | LC_NUMERIC=C gawk '{print $1 + 0}'
0.123

Ca a pas l'air d'etre modifiable a l'interieur du script awk
(ENVIRON["LC_ALL"]="C" est sans effet), ca pourrait etre
consideré comme un bug, pourtant, c'est le comportement specifié
par POSIX...

Donc, en gros, faut un wrapper sh autour du script awk:

#! /bin/sh -
":" +0 && "eval" "LC_ALL=C exec /usr/bin/awk -f "$0" ${1+"$@"}"

# mettre le script awk ici.

--
Stephane


Avatar
geo cherchetout
Le 26.11.2004 12:50, *Stephane Chazelas* a écrit fort à propos :

Ok, probleme identifié.

C'etait le LC_NUMERIC a fr_FR qui posait probleme. En France, le
point decimal est une virgule, donc gawk prenait "0.123123" pour
"0" (il attend 0,123123).


Bien vu ! gawk traite convenablement mon fichier dès lors que j'y
remplace les points décimaux par des virgules, ce qui sera facile à
inclure dans mon script.
En revanche, mawk ne travaille bien qu'avec des points.

Donc, en gros, faut un wrapper sh autour du script awk:

#! /bin/sh -
":" +0 && "eval" "LC_ALL=C exec /usr/bin/awk -f "$0" ${1+"$@"}"


En effet, ça marche parfaitement malgré le gentil message suivant :
awk: /home/geo/scripts/sc2.sh:2: warning: escape sequence `$' treated
as plain `$'

Merci encore.

Avatar
Stephane Chazelas
2004-11-26, 18:07(+01), geo cherchetout:
[...]
#! /bin/sh -
":" +0 && "eval" "LC_ALL=C exec /usr/bin/awk -f "$0" ${1+"$@"}"


En effet, ça marche parfaitement malgré le gentil message suivant :
awk: /home/geo/scripts/sc2.sh:2: warning: escape sequence `$' treated
as plain `$'
[...]


Rhaah, le chieur ! (pas toi, gawk)

S'il n'y avait pas eu le $"gettext-a-la-noix" de bash, on aurait
pu faire:

#! /bin/sh -
":" +0 && "eval" "LC_ALL=C exec /usr/bin/awk -f "$""0" $""{1+"$""@"}"


L'idee, c'est que awk ignore cette ligne et que le shell fasse:

LC_ALL=C exec /usr/bin/awk -f "$0" ${1+"$@"}
(pour lancer awk sur le meme fichier avec la meme liste
d'arguments).

Bon, je pense que ceci devrait marcher:

#! /bin/sh -
":" +0 && d="$" && eval "LC_ALL=C exec /usr/bin/awk -f
"${d}0" $d{1+"$d@"}"

(ca ne marche pas correctement toutefois si le script awk ne
contient que des clauses BEGIN).

--
Stephane


Avatar
Pascal Bourguignon
geo cherchetout writes:

Le 26.11.2004 12:50, *Stephane Chazelas* a écrit fort à propos :

Ok, probleme identifié.

C'etait le LC_NUMERIC a fr_FR qui posait probleme. En France, le
point decimal est une virgule, donc gawk prenait "0.123123" pour
"0" (il attend 0,123123).


Bien vu ! gawk traite convenablement mon fichier dès lors que j'y
remplace les points décimaux par des virgules, ce qui sera facile à
inclure dans mon script.
En revanche, mawk ne travaille bien qu'avec des points.

Donc, en gros, faut un wrapper sh autour du script awk:

#! /bin/sh -
":" +0 && "eval" "LC_ALL=C exec /usr/bin/awk -f "$0" ${1+"$@"}"


En effet, ça marche parfaitement malgré le gentil message suivant :
awk: /home/geo/scripts/sc2.sh:2: warning: escape sequence `$' treated
as plain `$'


Ceci dit, on peut aussi bien détecter la fréquence en travaillant sur
le passage à zéro que sur les crêtes. Même mieux, je dirais, puisque
les petits prasites influence moins les passages à zéro que les crêtes.
Pour cela, il aurait fallu ne pas redresser le signal!


--
__Pascal Bourguignon__ http://www.informatimago.com/
The world will now reboot; don't bother saving your artefacts.


1 2 3 4