The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Как из pipe офильтровать строки,а если их не было, то прервать?"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (Shell скрипты)
Изначальное сообщение [ Отслеживать ]

"Как из pipe офильтровать строки,а если их не было, то прервать?"  +/
Сообщение от Sphk on 08-Июл-12, 16:36 
Есть некий текстовый поток (gpspipe -r). Задача: получить первые 10 строк, проверить есть ли в них волшебное слово. Если нет слова, то - "аврал"

Проблема: в потоке может появиться только 3 строки, например. После чего gpspipe ждёт не появится ли чего. Чего-либо может не появится совсем, пока не будет устроен "аврал". Соответственно, есть время 10 секунд, больше которого нет смысла ждать.

Как отловить момент, что поток остановился и не потерять то, что оттуда уже получено?

Изобрёл нечто через fifo буфер, но, подозреваю, есть простые и давно реализованные средства и приёмы.


#!/bin/bash

magicWord="_abc"
wantedSign="DATA IS FOUND"
isSuccess="false"

# Если не ..., то создать ...
[ ! -e "/tmp/fifo" ] \
    && mkfifo --mode=600 /tmp/fifo

# Иммитатор потока + фильтр искомого. В фоне.
while read fakeData ; do
    [ "${fakeData}" == "${magicWord}" ] \
        && echo "${wantedSign}" > /tmp/fifo
done <<< "$( echo -en "${magicWord}\n_def\n_ghi\n" | head -n 10 )" \
&
while read fakeData ; do
    # cat /dev/zero = зависание, имитация паузы в потоке
    true
done <<< "$( cat /dev/zero | head -n 10 )" \
&
jobPId=${!}

# Даю время на сбор данных
echo "Job launched. Sleeping now."
sleep 5
echo "Going forward."

# Чтобы было, что прочитать из буфера и не зависнуть на чтении.
echo "stub" > "/tmp/fifo" &

# Поиск нужного в буфере, заодно опустошение буфера.
while read str ; do
    if [ "${str:0:${#wantedSign}}" == "${wantedSign}" ] ; then
        echo "Marker is found: ${str}"
        isSuccess="true"
    else
        echo "Stub found also: ${str}"
    fi
done < "/tmp/fifo"

# Конечная проверка - было ли найдено событие.
if [ "${isSuccess}" == "true" ] ; then
    echo "SUCCESS: Wanted data detected."
else
    echo "FAILURE: Data not found or timeout."
    exit 1
fi

[ -n "$( ps -o pid | grep ${jobPId})" ] \
    && kill -9 ${jobPId}


Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Как из pipe офильтровать строки,а если их не было, то прервать?"  +/
Сообщение от Andrey Mitrofanov on 08-Июл-12, 17:35 
> Есть некий текстовый поток (gpspipe -r). Задача: получить первые 10 строк, проверить
> есть ли в них волшебное слово. Если нет слова, то -
> "аврал"
> не будет устроен "аврал". Соответственно, есть время 10 секунд, больше которого
> нет смысла ждать.

10 строк или 10 секунд... Как-то так...

N=1000
S1=$(SECONDS+10))
while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
  read -t 1 line
  if [ $? -lt 128 ]; then
    echo "${N:1} : $line"
  fi
done


Может, ещё корректировку на скорость шела сделать:

-while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
-  read -t 1 line
+while [ $SECONDS -lt $S1 -a $N -le 1010 ]; do
+  while [ $N -le 1010 ] && read -t 1 line && [ $? -lt 128 ]; do
-  if [ $? -lt 128 ]; then
    echo "${N:1} : $line"
-  fi
+  done

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Как из pipe офильтровать строки,а если их не было, то прервать?"  +/
Сообщение от Andrey Mitrofanov on 08-Июл-12, 17:37 
>   fi

Кто-то пропустил -

    let N++

- но это _такие :) мелочи.

> done

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Как из pipe офильтровать строки,а если их не было, то прервать?"  +/
Сообщение от Sphk on 08-Июл-12, 21:01 
Ниже оба переработанных варианта в рабочей обёртке.

1) Можно ли как-то обойтись без kill в обоих вариантах? Если kill убрать, то зависнет. Висеть будет на строке возврата return, или - после её выполнения, но до выхода из блока. Кстати, тоже вопрос - где висит, как объяснить?

2) Не очевидно и тем неприятно, что до return убивается процесс источник потока. После | вызывается отдельный экземпляр shell, в котором и выполняется while. Возникает подозрение, о иерархии родитель-наследник, и тогда, что родитель (gpspipe) тушится до вызова возврата из наследника (блоки while). Всегда ли код возврата будет предсказуем?

3) В чём идея второго способа, относительного первого?

Вариант 1


#!/bin/bash

codeDataFound=11
codeTimeout=22

function probeGPS {
    local timeout=1 # Sec
    local maxStrQuantity=10
    local N=0

    gpspipe -r | while [ ${N} -le ${maxStrQuantity} ]; do
        read -t 1 line
        if [ ${?} -gt 128 ] ; then
            echo "Timeout at: N=${N}; line=${line};"
            #kill -9 $( pgrep -P ${$} gpspipe )
            return ${codeTimeout}
        fi
        if [ "${line:1:5}" == "GPRMC" ] ; then
            return ${codeDataFound}
        fi

        echo " S1=${S1}; N=${N}; line=${line:0:10};"

        ((N++))
    done
    return ${?}
}

probeGPS
case ${?} in
${codeDataFound})
    echo "Data found."
;;
${codeTimeout})
    echo "Timed out."
;;
esac

Вариант 2


#!/bin/bash

codeDataFound=11
codeTimeout=22

function probeGPS2 {
    local N=0
    local M=0
    local maxQuantity=10
    local timeout=1 # Sec

    echo "Level 0"
    gpspipe -r | while : ; do
        echo "Level 1 : Q=$((N+M));"
        while [ ${N} -le 10 ] && read -t ${timeout} line && [ ${?} -lt 128 ]; do
            echo "Level 2 : Q=$((N+M)); line=${line:0:10};"
            if [ "${line:1:5}" == "GPRMC" ] ; then
                return ${codeDataFound}
            fi
            ((M++))
        done
        ((N++))
        if [ $(( N+M )) -ge ${maxQuantity} ] ; then
            kill -9 "$( pgrep -P ${$} gpspipe )"
            return 22
        fi
    done
    return ${?}
}

probeGPS2
case ${?} in
${codeDataFound})
    echo "Data found."
;;
${codeTimeout})
    echo "Timed out."
;;
esac


Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2025 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру