在bash中处理二进制数据文件,查找大于某个数字的元素

时间:2010-12-07 09:51:25

标签: linux bash math command-line cygwin

我处理不同的二进制数据。大多数情况下,这些都是带符号的16位流。使用hexdump,它看起来像:

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

我希望只看到数据流的那些元素,这些元素大于或小于某个阈值(数据是二进制16位的符号)。它可能看起来像:

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

其中输出必须只给出大于2100且小于-2100的元素。有没有简单的命令行方法怎么做?

5 个答案:

答案 0 :(得分:0)

这样的一个班轮就像是:

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

答案 1 :(得分: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

答案 2 :(得分:0)

好吧,二进制...个人建议:不要使用普通的旧shell - 使用适合工作的工具。 Perl,Python,甚至是C / C ++程序 - 它们大多数都是单行程序。

以下是一个未经优化的黑客,可以给你一个想法:

#!/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

由于shell使用行分隔符来分割输入块,因此我不确定这是否可以通过简单的方法进行管道化。

答案 3 :(得分:0)

可以使Bash处理二进制数据。

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
}

示例(数据有意地显示奇数个字节以表明该函数适应这种情况):

$ 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

您的命令将是:

filter 2100 -2100 < data.pcm

答案 4 :(得分:0)

每当我想从二进制文件中提取数值时,我都使用od(八进制转储)。它有许多选项可用于提取字符,整数(8,16,32和64位)和浮点数(32位和64位)。您还可以指定要查找的确切值的偏移量。

要了解有关它的更多信息,请输入:

man od

然后,对bash中的od输出进行过滤不应该很复杂。