Czy bash może konsumować to samo fifo z dwóch oddzielnych poleceń?

5

Mam ogromne źródło danych, które filtruję za pomocą niektórych grep s.

Oto co robię teraz:

#!/bin/bash
param1='something'
param2='another'
param3='yep'
echo $(avro-read /log/huge_data | grep $param1 | grep "$param2-" | grep $param3 | wc -l) / $(avro-read /log/ap/huge_data | grep $param1 | grep -v "$param2-" | grep $param3 | wc -l) | bc -l

Zwróć uwagę na to, że robię najczęściej to samo filtrowanie dwa razy (jedna różnica za drugim razem), biorąc pod uwagę liczbę i dzieląc wynik końcowy. Jest to zdecydowanie hacky do zrobienia, ale chciałbym spróbować trochę przyspieszyć i wykonać początkowe filtrowanie tylko raz bez użycia pliku tymczasowego.

Próbowałem użyć fifo, ale nie jestem pewien, czy możliwe jest posiadanie dwóch procesów w jednym odczycie skryptu z niego, a także trzeci proces „czekanie”, aż oba zostaną wykonane, aby obliczyć wynik końcowy. Zajrzałem też do użycia tee, ale znowu nie wiem, jak zsynchronizować powstałe podprocesy.

EDYCJA: Sam rozwiązałem ten problem https://superuser.com/a/561248/43649 , ale oznaczył kolejną sugestię jako odpowiedź.

Andrew
źródło
Nie; gdy jeden proces odczytuje dane z fifo, dane te znikną i nie będą widoczne dla drugiego procesu.
chepner

Odpowiedzi:

2

Jeśli chcesz uniknąć tworzenia plików tymczasowych (lub przechowywania danych wyjściowych grep w zmiennej), możesz przekazać je do pętli for w następujący sposób:

#!/bin/bash

IFS=$'\n'
yay=0
nay=0

for line in `avro-read /log/huge_data | grep $param1 | grep $param3`; do
    [[ $line =~ $param2- ]] && yay=$(($yay + 1)) || nay=$(($nay + 1))
done

echo $yay / $nay \* 100 | bc -l

unset IFS

Stworzyłem zmodyfikowaną wersję podejścia w twoja odpowiedź to nie wymaga plików tymczasowych:

#!/bin/bash

(avro-read /log/huge_data | grep $param1 | grep $param3 | tee \
     >(echo yay=`grep -c "$param2-"`) \
     >(echo nay=`grep -vc "$param2-"`) \
     >/dev/null | cat ; echo 'echo $yay / $nay \* 100 | bc -l') | sh

Wydajność jednostki grep -c polecenia i echo polecenie zostanie wydrukowane jako

yay=123
nay=456
echo $yay / $nay \* 100 | bc -l

aby uniknąć warunków wyścigu 1 . Rurociągi do sh wykonuje wydrukowane polecenia.

1 Którykolwiek grep -c polecenie zakończy pierwsze wydrukuje pierwszą linię wyjścia.

Dennis
źródło
Super fajny sposób na przeglądanie danych.
Andrew
Świetnie - to sztuczka „trzeba pamiętać”, aby wyprowadzić wartości z podstawień procesu :)
mpy
Łał! Super fajny sposób na zrobienie tego. Dzięki za dostosowanie mojej odpowiedzi! Na pewno wiele się z tego nauczyć.
Andrew
1

Rozwiązałem to w ten sposób:

#!/bin/bash
param1='something'
param2='another'
param3='yep'

avro-read /log/huge_data | grep $param1 | grep $param3 \
| tee \
>(grep "$param2-" | wc -l | tr -d '\n' > has_count) \
>(grep -v "$param2-" | wc -l | tr -d '\n' > not_count) \
> /dev/null

echo $(cat has_count | tr -d '\n') '/' $(cat not_count | tr -d 'n') '* 100' | bc -l

Tak więc zamiast polegać na pliku fifo lub tymczasowym tee podzielić strumień na dwa oddzielne procesy, które po prostu wyprowadzają liczbę! W ten sposób nie muszę próbować synchronizować dwóch procesów przed próbą podzielenia liczby.

Andrew
źródło
Używasz dwóch plików tymczasowych ...
mpy
Bardzo interesujące! W odpowiedzi zawarłem modyfikację twojego podejścia, która nie wymaga plików tymczasowych.
Dennis
W tym przypadku „nie polegając na pliku tymczasowym” miałem na myśli plik tymczasowy pełen rzeczywistych danych. W tym przypadku to tylko przechowywanie numeru.
Andrew
0

Hm, zsh ma funkcję o nazwie MULTIOS. Dzięki temu możliwe jest połączenie jednego procesu z dwoma procesorami fifo. Jeśli jest to opcja, małe demo:

#!/bin/zsh -f

setopt multios

mkfifo f1 f2 2> /dev/null

param1='something'
param2='another'
param3='yep'

{ avro-read /log/huge_data | grep $param1 | grep $param3 } > f1 > f2 &

( cat f1 | grep $param2 | wc -l > value1 ) &!
value2=$(cat f2 | grep -v $param2 | wc -l)

print $(( 1. * $( cat value1 ) / $value2 ))

rm value1

Nie udało mi się jednak znaleźć sposobu na obejście pliku tymczasowego value1, czego prawdopodobnie należy unikać, jak zauważył Dennis. Ale być może spodoba ci się to rozwiązanie.

mpy
źródło