2016-04-04 7 views
0

У меня есть исполняемый файл cpp (mycat), который непрерывно считывает потоковый аудиопоток из разделяемой памяти и передает данные в stdOut и информацию метаданных в stdErr. mycat трубы из 12 линий для каждой записи аудиопотока, содержащих метаданные информации, глядя, как это:Bash: capture stdError from looped stream

0x1 (TimeStamp) 12Bytes:2956 +  6793/(47999+1) (0.141521) delta= 0+ 1536/(47999+1) (0.032000) 2956.151418 -9.898ms 2016.04.04 16:06:37.700 
0x4 (ReferenceTime) 12Bytes:2956 + 6156972/(26999999+1) (0.228036) delta= 0+ 1618519/(26999999+1) (0.059944) 2956.151426 76.610ms 2016.04.04 16:06:37.700 
0x6 (ProcessDelay) 4Bytes: 64 (0x40) 
0x7 (ClockAccuracy) 8Bytes: offset=0.000ppm (+-0.000ppm) 
0xb (ClockId) 8Bytes: 01 00 00 00 42 22 01 00 
0x20001 (SampleRate) 4Bytes: 48000 (0xbb80) 
0x20002 (Channels) 4Bytes: 6 (0x6) 
0x20003 (PcmLevel) 24Bytes: -21307 -20348 -31737 -42427 -28786 -26525 
0x20004 (PcmPeak) 24Bytes: -14366 -13360 -25203 -39427 -19067 -21307 
0x2000e (DolbyDpMetadata) 39352Bytes: 
Linear Time: 2956 +  6793/(47999+1) (0.141521) delta= 0+ 1536/(47999+1) (0.032000) 
2016.04.04 16:06:37.700 update: slot=0xe2840 validTo=0x3d1dd180 shmT=0x3d195200 (delta=294784) doffset=0xec2c0 msize=39552 dsize=18432 type=0x20001 (PCMS16) data bytes: df f4 f2 fc 

Что я хочу Баш скрипт, который:

1) запуск mycat например. ./mycat shm_name > /dev/null.

2) читает stdErr от mycat до 12-й строки независимо от того, где она началась.

2,1) В конце концов, хранить 12 строку в переменную (это необязательно)

3) immedialy убивает mycat после 12-й линии, так что сценарий Баш может продолжаться без раздражен stdError исходящего.

4) Считать значение линии «каналов» (в данном случае 6) и сохранить ее в переменную с именем «каналы»

5) Считать значение линии «SampleRate» (в данном случае 48000) и сохраните переменную под названием «rate»

есть ли способ сделать это?

ответ

0

я найти элегантное решение:

while read -r line;           # Read mycat line by line 
do 
    if echo "$line" | grep -qi "SampleRate"; then   # Search for line containing string 'SampleRate' 
     rate="${line#*:}";         # Remove all charachters till ':' 
     rate="${rate%(*}";         # Remove all charachters from '(' 
     rate="$(echo -e "${rate}" | tr -d '[[:space:]]')" # Remove all tralling withespace 
    elif echo "$line" | grep -qi "Channels"; then 
     channels="${line#*:}"; 
     channels="${channels%(*}"; 
     channels="$(echo -e "${channels}" | tr -d '[[:space:]]')" 
    fi 

    if [ -n "$channels" ] && [ -n "$rate" ]; then   # If both variables 'channels' and 'rate' are not empty kill the while loop 
     break; 
    fi 
done < <(./mycat $shm_name 2>&1 > /dev/null)   # Mycat is processed into a while loop, standard Error is redirected to standard Output (2>&1) 

echo "Found datarate: $rate" 
echo "Found channels: $channels" 
0

Вы можете перенаправить stderr с помощью mycat shm_name > /dev/null 2>/path/to/file. Когда придет время, вы можете убить mycat killall mycat. Для хранения переменных вы хотите export channels =, тот же шаблон со скоростью. Вы можете найти их с grep. Я не уверен, как подождать ровно двенадцать строк.

0

Во-первых, вам необходимо перенаправить STDERR на STDOUT и STDOUT перейти к null.

mycat 2>&1 >/dev/null | parsing_script 

Тогда вам нужен скрипт синтаксического анализа для сбора данных

#!/bin/bash 

declare -a data=() 
count=1 
while read line; do 
    data+=("$line 
    ") 
    ((count++)) 

    string=$(echo $line|sed 's/.*(\(.[A-Za-z]*\)).*/\1/') 
    case $string in 
     SampleRate) rate=$(echo $line|sed 's/.*: \(.[0-9]*\) .*/\1/') 
     ;; 
     Channels) channels=$(echo $line|sed 's/.*: \(.[0-9]*\) .*/\1/') 
     ;; 
     *) true;; 
    esac 
    if [[ $count -gt 12 ]]; then 
     break 
    fi 
done <&0 

echo $channels 
echo $rate 

Я echo'd значения, но вы можете перенаправить их в файл, форматировать их, и т.д. Кроме того, данные $ { [@]} содержит ваши метаданные. Поскольку вы работаете на трубопроводах, я читаю от STDIN, но это может быть более надежным, если вы хотите настроить его.