OVH Cloud OVH Cloud

substitution en temps reel

21 réponses
Avatar
geo cherchetout
Bonjour,
Je bricole sous GNU/Linux-Mandriva 2006. Je reçois par le port série de
mon pc des résultats de mesures successives en provenance d'un «
scopemètre ». Ces résultats se présentent sous la forme de lignes comme
suit :

$ cat /dev/ttyS0

k0s0Gs0CNOW rms AC+DC 1.125mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.132mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.139mV, 0Hz, OL

...

Je souhaiterais que chaque enregistrement comporte, en remplacement de
la chaîne « k0s0Gs0CNOW » la date et l'heure de réception des données.
Je tatonne avec sed mais vainement. Par exemple, j'ai essayé :
$ cat /dev/ttyS0 | sed "s/k0s0Gs0CNOW/`date`/g" ou
$ sed -e 's/k0s0Gs0CNOW/`date`/g' < /dev/ttyS0
mais la date n'apparaît pas dans les mesures affichées.
Un petit coup de pouce, svp ?

10 réponses

1 2 3
Avatar
geo cherchetout
Le 04.02.2006 17:36, *Stephane Chazelas* a écrit fort à propos :

$ gawk '{sub(/k0s0Gs0CNOW/, strftime("%F %T")); print}' /dev/ttyS0
k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

...

Aucune substitution n'est faite.
[...]


etrange. Et ca donne quoi quand tu fais

od -c /dev/ttyS0

?




À l'arrivée de la première mesure :

$ od -c /dev/ttyS0
0000000 033 & k 0 s 0 G 033 & s 0 C N O W
0000020 r m s A C + D C 1 . 0 0 0
0000040 m V , 0 H z , O L r
0000060 n n 033 & k 0 s 0 G 033 & s 0 C N O
0000100 W r m s A C + D C 1 . 0
0000120 0 0 m V , 0 H z , O


Avatar
Stephane Chazelas
2006-02-04, 18:20(+01), geo cherchetout:
Le 04.02.2006 17:36, *Stephane Chazelas* a écrit fort à propos :

$ gawk '{sub(/k0s0Gs0CNOW/, strftime("%F %T")); print}' /dev/ttyS0
k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

k0s0Gs0CNOW rms AC+DC 1.000mV, 0Hz, OL

...

Aucune substitution n'est faite.
[...]


etrange. Et ca donne quoi quand tu fais

od -c /dev/ttyS0

?




À l'arrivée de la première mesure :

$ od -c /dev/ttyS0
0000000 033 & k 0 s 0 G 033 & s 0 C N O W
0000020 r m s A C + D C 1 . 0 0 0
0000040 m V , 0 H z , O L r
0000060 n n 033 & k 0 s 0 G 033 & s 0 C N O
0000100 W r m s A C + D C 1 . 0
0000120 0 0 m V , 0 H z , O


Tu ne nous as pas tout dit, il y a ces caracteres ESC et & qui
n'apparaissaient pas dans ton premier post.

C'est 33&k0s033&Gs0CNOW que tu veux remplacer, pas
k0s0Gs0CNOW.

gawk '{sub(/33&k0s033gGs0CNOW/, strftime("%F %T")); print}'

Ou si c'est le premier mot:

gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}'

--
Stéphane



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

Tu ne nous as pas tout dit, il y a ces caracteres ESC et & qui
n'apparaissaient pas dans ton premier post.


Je vois, ce sont des caractères clandestins qui avaient échappé à mon
regard. (Ils n'apparaissent évidemment ni dans konsole ni dans un
fichier texte recevant les mesures.)

C'est 33&k0s033&Gs0CNOW que tu veux remplacer, pas
k0s0Gs0CNOW.

gawk '{sub(/33&k0s033gGs0CNOW/, strftime("%F %T")); print}'


Exact, ça marche. :-)

Ou si c'est le premier mot:

gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}'


En effet, c'est bon aussi. J'aurai encore appris des choses, merci beaucoup.

Avatar
geo cherchetout
Je vois, ce sont des caractères clandestins qui avaient échappé à mon
regard. (Ils n'apparaissent évidemment ni dans konsole ni dans un
fichier texte recevant les mesures.)


Explication : Ces données sont normalement destinées à une imprimante.
Je ne l'avais pas remarqué quand il s'agit comme ici de résultats de
mesures sous forme alphanumérique, mais certains caractères non
imprimables changent un peu selon que l'appareil est configuré pour
attaquer une imprimante HP - comme c'était le cas ici - ou une Epson.

gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}'



Le mérite de cette commande est qu'elle donne un aussi bon résultat quel
que soit le type d'imprimante choisi parmi les deux possibles.
Comme celle proposée par Luc, qui présente à mes yeux l'avantage de ne
faire appel à rien d'extérieur au shell. (Donc un peu moins difficile à
assimiler, il me semble.)

Merci à tous et bon dimanche.


Avatar
Stephane Chazelas
2006-02-04, 21:35(+01), geo cherchetout:
Je vois, ce sont des caractères clandestins qui avaient échappé à mon
regard. (Ils n'apparaissent évidemment ni dans konsole ni dans un
fichier texte recevant les mesures.)
[...]


gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}'



Le mérite de cette commande est qu'elle donne un aussi bon résultat quel
que soit le type d'imprimante choisi parmi les deux possibles.
Comme celle proposée par Luc, qui présente à mes yeux l'avantage de ne
faire appel à rien d'extérieur au shell. (Donc un peu moins difficile à
assimiler, il me semble.)
[...]


Dans celle de Luc:

while read A B; do
test -n "$B" && printf '%s %sn' "`date`" "$B"
done < /dev/ttyS0

Il faut voir que les espacements autour du premier mot, et a la
fin ne sont pas conservés et que ca ne se passera pas bien si
l'input contient des blackslashes.

De plus, ca lance 4 outils par ligne d'input (meme si 3
d'entre eux sont en general builtin dans le shell) alors que la
solution gawk comprend un appel d'outil pour toutes les lignes
d'input.

En shell, on prefere utiliser des outils "filtres" que l'on pipe
ensemble. La solution d'ecrire une boucle en shell directement
est un peu prendre un shell pour un language de programmation,
ce qu'il n'est pas vraiment.

Cela dit, la solution de Luc a l'avantage d'etre portable
(conforme a la specification Unix). gawk est une commande GNU.
Le awk standard Unix ne connait pas strftime.

De nos jours, on peut compter sur perl, souvent meme plus
surement que sur le shell et ses outils /standard/.

perl -MPOSIX -pe 's/S+/strftime("%F %T", localtime)/e' /dev/ttyS0

--
Stéphane



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

...
De nos jours, on peut compter sur perl, souvent meme plus
surement que sur le shell et ses outils /standard/.


Merci pour toutes ces explications dont je crois comprendre une bonne
partie, et pour cette dernière solution. Avec toutes j'obtiens désormais
un affichage parfait à l'écran mais j'ai encore un problème avec tes
solutions que je n'ai pas avec celle de Luc : Comment recueillir les
données horodatées dans un fichier ? C'est sûrement évident pour tout le
monde mais pas pour moi, qui ne connais aucun langage de programmation.
Je récapitule tes 2 propositions :

gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}' < /dev/ttyS0

perl -MPOSIX -pe 's/S+/strftime("%F %T", localtime)/e' /dev/ttyS0

Avatar
Stephane Chazelas
On Wed, 08 Feb 2006 15:23:35 +0100, geo cherchetout wrote:
[...]
solutions que je n'ai pas avec celle de Luc : Comment recueillir les
données horodatées dans un fichier ? C'est sûrement évident pour tout le
monde mais pas pour moi, qui ne connais aucun langage de programmation.
Je récapitule tes 2 propositions :

gawk '{sub(/[^[:blank:]]+/, strftime("%F %T")); print}' < /dev/ttyS0

perl -MPOSIX -pe 's/S+/strftime("%F %T", localtime)/e' /dev/ttyS0


Rajoute "> fichier" ou si tu veux les avoir aussi a l'ecran,
rajouter "| tee fichier"

perl -MPOSIX -pe 's/S+/strftime("%F %T", localtime)/e
' < /dev/ttyS0 > fichier

Ce qui va arriver, par contre, c'est que comme perl ou awk
voient que leur sortie standard n'est plus un terminal, ils vont
bufferiser leur sortie (eviter de tout envoyer au fichier a
chaque fois qu'il y a quelque chose a ecrire, mais envoyer par
blocs quand il y en a suffisemment). Les lignes auront le bon
horodatage, mais le contenu du fichier ne sera pas mis a jour
immediatement.

Si ca ne te convient pas, tu peux dire a gawk de "flusher" son
buffer apres chaque ecriture:

gawk '
{
sub(/[^[:blank:]]+/, strftime("%F %T"))
print
fflush()
}' < /dev/ttyS0 > fichier

pour perl, tu peux positionner la variable $OUTPUT_AUTOFLUSH ($|
en plus court) a 1:

perl -MPOSIX -pe '
BEGIN{$OUTPUT_AUTOFLUSH = 1}
s/S+/strftime("%F %T", localtime)/e
' < /dev/ttyS0 > fichier

--
Stephane

Avatar
lhabert
Stephane Chazelas :

La solution d'ecrire une boucle en shell directement est un peu prendre un
shell pour un language de programmation, ce qu'il n'est pas vraiment.


Tentative de lancé de troll?

Avatar
Pascal Bourguignon
(Luc Habert) writes:

Stephane Chazelas :

La solution d'ecrire une boucle en shell directement est un peu prendre un
shell pour un language de programmation, ce qu'il n'est pas vraiment.


Tentative de lancé de troll?


Non, simple suggestion: écrire "if" ou "while" ou "for" dans un script
est un signe qu'il y a une bogue sur la première ligne; au lieu de:

#!/bin/bash

il faudrait mettre:

#!/usr/bin/clisp


--
__Pascal Bourguignon__ http://www.informatimago.com/
Litter box not here.
You must have moved it again.
I'll poop in the sink.


Avatar
Stephane Chazelas
On Wed, 08 Feb 2006 16:10:00 +0100, Pascal Bourguignon wrote:
[...]
Non, simple suggestion: écrire "if" ou "while" ou "for" dans un script
est un signe qu'il y a une bogue sur la première ligne; au lieu de:

#!/bin/bash

il faudrait mettre:

#!/usr/bin/clisp
[...]


pas plus de bash dans /bin que de clisp dans /usr/bin, ici, je
dois dire.

Personnellement, c'est pour une bonne partie lisp qui m'a
degouté d'emacs. Pas assez lisible.

--
Stephane

1 2 3