LINUX.ORG.RU

История изменений

Исправление aureliano15, (текущая версия) :

prog | sed выводит в реальном времени, а с awk нет

и

Всё таки это awk тормозит.

Весьма странно. awk не должна тормозить в такой ситуации даже на слабом компе, а буфер в моём однострочнике точно ни при чём.

Я думаю всё таки поможет read, который вы описали выше.

Попробуйте вместо awk подставить такой bash скрипт:

#!/bin/bash

while true;
 do
   read var;
   if [ "$(echo $var | grep -F '.')" ];
     then
       vari="$(echo -n $var | sed 's/\..*//')";
       varf="$(echo -n $var | sed 's/.*\.//')";
   else
     if [ -n "$var" ];
       then
         vari=$var;
         varf=0;
     else
         # Если вместо continue поставить break,
         # то при встрече пустой строки скрипт прервётся:
         continue;
     fi;
   fi;
   if [ -z "$vari" ];
     then
       vari=0;
   fi;
   echo -n "$var: ";
   if [ "$vari" -gt -100 -a "$vari" -lt 100 ];
     then
       echo Ok.;
   else
     if [ "$vari" -lt -100 -o "$vari" -gt 100 -o "$varf" -gt 0 ];
       then
         echo Alert.;
     else
         echo Ok.;
     fi;
   fi;
 done

Этот скрипт учитывает цифры и после точки.

Можно ещё попробовать вместо awk, скрипта и sed’а такую c-программку:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  double n;
  char *ptr, *endptr, buf[4096];
  while(!feof(stdin))
  {
    if((endptr=fgets(buf, sizeof(buf), stdin))!=NULL)
    {
      do
      {
        ptr=endptr;
        n=strtod(ptr, &endptr);
        if(endptr && endptr!=ptr)
         printf("%f: %s.\n", n, n<-100.0 || n>100.0 ? "Alert" : "Ok");
      } while(*endptr && endptr!=ptr);
    }
  }
  return 0;
}

Компилируете её командой gcc -o alert100 -Wall -O3 -g0 alert100.c, где alert100.c — название исходника, а alert100 — название выходной исполняемой программы, вместо них можно придумать свои названия. И затем запускаете командой prog | ./alert100. Программа умеет читать по нескольку чисел из строки, поэтому sed ей не нужен. Массив buf для входной строки я установил в 4096. Если строки могут быть больше, то нужно увеличить это число. Если же строки абсолютно всегда намного меньше, то можно уменьшить, но так, чтоб помимо строки в buf помещалось ещё по меньшей мере 2 символа: символ новой строки и 0. В выводе программы есть одно отличие: числа с большим числом 0 после точки округляются при выводе, но не при сравнениях, из-за чего иногда можно увидеть что-то вроде:

-100.000000: Alert.
100.000000: Alert.
-100.000000: Ok.
100.000000: Ok.

Чтоб Alert и Ok соответствовали выводимому числу в таких случаях, достаточно увеличить точность вывода с помощью флагов форматирования в функции printf.

Обязательно отпишитесь, помогли или не помогли эти варианты. Потому что самому стало интересно, что у вас там с awk происходит.

Мне нужно что бы alert запускался одноразово и сценарий закрывался.

Этого в исходной формулировке задачи не было. Для этого в bash и awk есть команда exit, а в языке си — оператор return.

Исходная версия aureliano15, :

prog | sed выводит в реальном времени, а с awk нет

и

Всё таки это awk тормозит.

Весьма странно. awk не должна тормозить в такой ситуации даже на слабом компе, а буфер в моём однострочнике точно ни при чём.

Я думаю всё таки поможет read, который вы описали выше.

Попробуйте вместо awk подставить такой bash скрипт:

#!/bin/bash

while true;
 do
   read var;
   if [ "$(echo $var | grep -F '.')" ];
     then
       vari="$(echo -n $var | sed 's/\..*//')";
       varf="$(echo -n $var | sed 's/.*\.//')";
   else
     if [ -n "$var" ];
       then
         vari=$var;
         varf=0;
     else
         # Если вместо continue поставить break,
         # то при встрече пустой строки скрипт прервётся:
         continue;
     fi;
   fi;
   if [ -z "$vari" ];
     then
       vari=0;
   fi;
   echo -n "$var: ";
   if [ "$vari" -gt -100 -a "$vari" -lt 100 ];
     then
       echo Ok.;
   else
     if [ "$vari" -lt -100 -o "$vari" -gt 100 -o "$varf" -gt 0 ];
       then
         echo Alert.;
     else
         echo Ok.;
     fi;
   fi;
 done

Этот скрипт учитывает цифры и после точки.

Можно ещё попробовать вместо awk, скрипта и sed’а такую c-программку:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  double n;
  char *ptr, *endptr, buf[4096];
  while(!feof(stdin))
  {
    if((endptr=fgets(buf, sizeof(buf), stdin))!=NULL)
    {
      do
      {
        ptr=endptr;
        n=strtod(ptr, &endptr);
        if(endptr && endptr!=ptr)
         printf("%f: %s.\n", n, n<-100.0 || n>100.0 ? "Alert" : "Ok");
      } while(*endptr && endptr!=ptr);
    }
  }
  return 0;
}

Компилируете её командой gcc -o alert100 -Wall -O3 -g0 alert100.c, где alert100.c — название исходника, а alert100 — название выходной исполняемой программы, вместо них можно придумать свои названия. И затем запускаете командой prog | ./alert100. Программа умеет читать по нескольку чисел из строки, поэтому sed ей не нужен. Массив buf для входной строки я установил в 4096. Если строки могут быть больше, то нужно увеличить это число. Если же строки абсолютно всегда намного меньше, то можно уменьшить, но так, чтоб помимо строки в buf помещалось ещё по меньшей мере 2 символа: символ новой строки и 0. В выводе программы есть одно отличие: числа с большим числом 0 после точки округляются при выводе, но не при сравнениях, из-за чего иногда можно увидеть что-то вроде:

-100.000000: Alert.
100.000100: Alert.
-100.000000: Ok.
100.000100: Ok.

Чтоб Alert и Ok соответствовали выводимому числу в таких случаях, достаточно увеличить точность вывода с помощью флагов форматирования в функции printf.

Обязательно отпишитесь, помогли или не помогли эти варианты. Потому что самому стало интересно, что у вас там с awk происходит.

Мне нужно что бы alert запускался одноразово и сценарий закрывался.

Этого в исходной формулировке задачи не было. Для этого в bash и awk есть команда exit, а в языке си — оператор return.