2010-12-07 6 views
0

Je traite différentes données binaires. Généralement, ce sont des flux 16 bits signés. Avec hexdump, il ressemble à:Traitement des fichiers de données binaires dans bash, recherche des éléments supérieurs à un certain nombre

... 
2150  -191 -262 15  -344 -883 -820 -1038 -780 
-1234 -1406 -693 131  433  396  241  600  1280 
... 

Je voudrais voir que les éléments d'un flux de données, qui sont supérieures ou inférieures à un certain seuil (données est binaire signé 16 bits). Il pourrait ressembler à:

cat data.pcm | $($here_some_filtering) 2100 -2100 

où la production doit me donner que des éléments qui sont supérieurs à 2100 et inférieur à -2100. Y a-t-il une méthode de ligne de commande simple comment le faire?

+1

Cela ressemble à une idée brutalement terrible. Pourquoi êtes-vous opposé à l'utilisation d'un outil plus performant? –

+0

@Ignacio: de nombreuses plates-formes mobiles fournissent uniquement un support bash/sh de base, pas de python, pas de perl – psihodelia

Répondre

0
$ cat pcm 
2150  -191 -262 15  -344 -883 -820 -1038 -780 
-1234 -1406 -693 131  433  396  241  600  1280 

$ for num in $(< pcm); do ((num > 2100 || num < -2100)) && echo $num; done 
2150 
+0

Votre entrée est incorrecte. –

+0

@Ignacio Vazquez-Abrams peut-être que c'est vrai, mais c'est ce que le PO a donné et c'est tout ce que j'ai à faire. – SiegeX

+0

pcm doit être une donnée binaire, tous les 2 octets représentent un entier signé de 16 bits; Quoi qu'il en soit, merci, très simple, facile à retenir, et belle solution – psihodelia

0

Une doublure pour ce serait quelque chose comme:

for c in `cat data.pcm`; do if [ $c -lt -2100 -o $c -gt 2100 ]; then echo $c; fi; done 
+1

Maintenant, tout ce que vous avez à faire est de le convertir depuis et vers les données binaires. –

0

Eh bien, suggestion binaire ... personnelle: Ne pas utiliser shell bon vieux - utiliser un ajustement outil pour le travail. Perl, Python, même un programme en C/C++ - ce sera surtout un one-liners dans ceux-ci.

Voici un bidouille unoptimized pour vous donner une idée:

#!/bin/bash 
lowerlimit=-333; 
upperlimit=333; 
filesize=`wc -c "$1" | cut -d' ' -f1`; 

off=0; 
while [ $off -lt $filesize ]; do 
    shortval=$(od -An -s -N 2 -j $off "$1") 
    test $shortval -gt $lowerlimit && 
    test $shortval -lt $upperlimit && 
    dd if="$1" bs=1 count=2 skip=$off 2>/dev/null 
    off=$(($off + 2)) 
done 

Je ne suis pas sûr que cela peut être pipe en mesure de manière simple en raison du fait que le shell utilise des séparateurs de ligne à diviser les blocs d'entrée.

+0

de nombreuses plates-formes mobiles fournissent uniquement bash/sh soutien de base, pas de python, pas perl – psihodelia

+0

Ils ont également souvent pas les outils usermode pleine capacité (mais par exemple busybox au lieu de cela, qui fournit de nombreuses commandes, mais ne répond pas à 100% de compatibilité de l'option de ligne de commande). Vous devrez tester par exemplesi 'od' sur l'appareil aura toutes les options ci-dessus. –

0

Bash peut être fait pour traiter des données binaires.

getbyte() { 
    local IFS= LC_CTYPE=C res c 
    read -r -d '' -n 1 c 
    res=$? 
    # the single quote in the argument of the printf 
    # yields the numeric value of $c (ASCII since LC_CTYPE=C) 
    [[ -n $c ]] && c=$(printf '%d' "'$c") || c=0 
    printf "$c" 
    return $res 
} 

filter() { 
    local b1 b2 val 
    while b1=$(getbyte) 
    do 
     b2=$(getbyte) 
     ((val = b2 * 256 + b1)) 
     ((val = val > 32767 ? val - 65536 : val)) 
     if ((val > ${1:-0} || val < ${2:-0})) 
     then 
      echo $val 
     fi 
    done 
} 

Exemples (les données ont un nombre impair d'octets intentionnellement pour montrer que la fonction accueille cette condition):

$ data='\0\01\010\0377\0377\0100\0300\0200\0333' 
$ echo -en "$data" | filter 
256 
-248 
16639 
-32576 
219 
$ echo -en "$data" | filter 222 -333 
256 
16639 
-32576 

Votre commande serait alors:

filter 2100 -2100 < data.pcm 
0

Chaque fois que je vouloir extraire des valeurs numériques à partir d'un fichier binaire, j'utilise od (vidage octal). Il a beaucoup d'options pour extraire des caractères, entiers (8, 16, 32 et 64 bits) et flottants (32 et 64 bits). Vous pouvez également spécifier un décalage à la valeur exacte que vous recherchez.

Pour en apprendre davantage à ce sujet, tapez:

man od 

Ensuite, le filtrage sur od sortie ne devrait pas être complexe bash.

Questions connexes