Je prépare une présentation pour un public non technique. J'ai un programme en bash qui produit un stream continu de valeurs, dont quelques-unes sont importantes. Je voudrais souligner les résultats importants tels qu'ils sont affichés afin que le public puisse avoir une idée de leur fréquence. Le problème est que je ne peux pas get sed
pour fonctionner sur un stream en cours d'exécution. Cela fonctionne bien si je mets les résultats dans un file, comme dans:
cat output.txt | sed "s/some text/some text bolded/"
Mais si j'essaie la même chose sur la sortie courante, comme ceci:
command | sed "s/some text/some text bolded/"
sed
ne fait rien. Des pensées?
Comme Lambert était assez utile pour le souligner, mon affirmation que sed
ne faisait rien n'était vague. Ce qui se passe est que le programme sort vers stdout
(je suis quasiment sûr que ce n'est pas écrit sur stderr
) comme il le ferait normalement, même s'il est passé par sed
.
Le problème semble être que la command appelle un deuxième programme, qui sort ensuite à stdout. Il y a quelques lignes imprimées par le premier programme; ceux-ci je peux éditer. Ensuite, il y a un stream de valeurs imprimées par le deuxième programme; ceux-ci je ne peux pas éditer.
Les methods Perl et awk ne fonctionnent pas non plus.
Les chances sont que la sortie de la command est tamponnée. Lorsque la command écrit sur un terminal, le tampon est vidé sur chaque nouvelle ligne, de sorte que vous voyez qu'il apparaît au taux attendu. Lorsque la command écrit dans un tube, le tampon est seulement vidé lorsqu'il atteint quelques kilo-octets, donc il est très lent. C'est le comportement par défaut de la bibliothèque d'inputs / sorties standard.
Pour forcer la command à ne pas surcharger sa sortie, vous pouvez utiliser unbuffer
(à partir de expect) ou stdbuf
(à partir de GNU coreutils).
unbuffer command | sed … stdbuf -o0 command | sed …
J'utiliserais awk
command | awk '/some important stuff/ { printf "%c[31m%s%c[0m\n",27,$0,27 ; next } { print ; } '
où
/some important stuff/
select une ligne importante, comme dans sed printf "%c[31m%s%c[0m\n",27,$0,27 ;
imprimer en rouge
le point key est que la command
devrait rincer les lignes, mais cela devrait être le cas si vous avez beaucoup de sortie.
La manière perl:
command | perl -pe 's/(stuff)/\x1b[1m$1\x1b[0m/g'
ou avec une sortie continue:
Un script bash pour la sortie cont
:
#!/bin/bash while [ true ] do echo "Some stuff" done
Testez avec:
./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
\x1b[1m
– audace ou intensité accrue ${1}
– le backreferenze \x1b[0m
– réinitialise tous les attributes Sortie:
Quelques trucs
Quelques trucs
Quelques trucs
Quelques trucs
Plus de codes d'échappement ici .
sed
a une option pour cela:
-u, –unbuffered
Ce qui charge des quantités minimes de données à partir des files d'input et vire les tampons de sortie plus souvent. Voir man sed
pour plus de détails.