当前位置: 首页 > 面试题库 >

Linux上的二进制grep?

刘俊语
2023-03-14
问题内容

说我已经生成了以下二进制文件:

# generate file:
python -c 'import sys;[sys.stdout.write(chr(i)) for i in (0,0,0,0,2,4,6,8,0,1,3,0,5,20)]' > mydata.bin

# get file size in bytes
stat -c '%s' mydata.bin

# 14

并说,我想0x00使用类似grep的语法查找全零()的位置。

到目前为止,我能做的最好的事情是:

$ hexdump -v -e "1/1 \" %02x\n\"" mydata.bin | grep -n '00'

1: 00
2: 00
3: 00
4: 00
9: 00
12: 00

但是,这会将原始二进制文件中的每个字节隐式转换为多字节ASCII表示形式,并可以对其进行grep操作;不完全是优化的主要示例:)

是否有类似grepLinux 的二进制文件?也可能支持某种类似于正则表达式的语法,但也支持字节“字符”的东西-也就是说,我可以编写类似“
a(\x00*)b”的东西,并在字节“ a”之间匹配字节0的“零个或多个”出现( 97)和“ b”(98)?

编辑:上下文是我正在一个驱动程序上,我捕获8位数据;数据出了点问题,可能是千字节到兆字节,我想检查特定的签名及其出现的位置。(
到目前为止,我正在使用千字节片段,因此优化并不是那么重要-但是,如果我开始在兆字节长捕获中遇到一些错误,并且需要分析这些错误,我想我想进行一些优化:)。
特别是,我希望可以在其中“ grep”一个字节作为字符- hexdump强迫我按字节搜索字符串

EDIT2:相同的问题,不同的论坛:)
grepping二进制文件中的字节序列

EDIT3:多亏了@tchrist的回答,这也是一个“抓紧”和匹配并显示结果的示例( 尽管与OP不太相同 ):

$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin

ca000000cb000000cc000000cd000000ce     # Matched data (hex)
66357                                  # Offset (dec)

要将匹配的数据每个分组为一个字节(两个十六进制字符),则需要为匹配的字符串中存在的多个字节指定“ H2 H2 H2 …”;因为我的比赛’
.....\0\0\0\xCC\0\0\0.....‘覆盖了17个字节,所以我可以"H2"x17在Perl中写’ ‘。这些“
H2”中的每一个都将返回一个单独的变量(如列表中所示),因此join还需要用于在它们之间添加空格-最终:

$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin

ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357

好吧..实际上Perl是非常好的“二进制grepping”工具,我必须承认:)只要一个人正确地学习语法:)


问题答案:

单线输入

这是较短的单线版本:

% perl -ln0e 'print tell' < inputfile

这是一个稍长的单线:

% perl -e '($/,$\) = ("\0","\n"); print tell while <STDIN>' < inputfile

连接这两个单行代码的方法是通过取消编译第一个程序的程序:

% perl -MO=Deparse,-p -ln0e 'print tell'
BEGIN { $/ = "\000"; $\ = "\n"; }
LINE: while (defined(($_ = <ARGV>))) {
    chomp($_);
    print(tell);
}

程序输入

如果您想将其放在文件中,而不是从命令行调用它,那么这里是一个更明确的版本:

#!/usr/bin/env perl

use English qw[ -no_match_vars ];

$RS  = "\0";    # input  separator for readline, chomp
$ORS = "\n";    # output separator for print

while (<STDIN>) {
    print tell();
}

这是很长的版本:

#!/usr/bin/env perl

use strict;
use autodie;  # for perl5.10 or better
use warnings qw[ FATAL all  ];

use IO::Handle;

IO::Handle->input_record_separator("\0");
IO::Handle->output_record_separator("\n");

binmode(STDIN);   # just in case

while (my $null_terminated = readline(STDIN)) {
    # this just *past* the null we just read:
    my $seek_offset = tell(STDIN);
    print STDOUT $seek_offset;

}

close(STDIN);
close(STDOUT);

单线输出

顺便说一句,要创建测试输入文件,我没有使用过长的Python大型脚本;我只是使用了这个简单的Perl单行代码:

% perl -e 'print 0.0.0.0.2.4.6.8.0.1.3.0.5.20' > inputfile

您会发现,完成相同的工作,Perl通常比Python短2-3倍。而且您不必在清晰度上妥协;有什么比上面的一线简单?

程序输出

我知道我知道。如果您还不懂该语言,这可能会更清楚:

#!/usr/bin/env perl
@values = (
    0,  0,  0,  0,  2,
    4,  6,  8,  0,  1,
    3,  0,  5, 20,
);
print pack("C*", @values);

尽管这也可行:

print chr for @values;

一样

print map { chr } @values;

尽管对于那些喜欢所有严谨,细心和全部的人来说,这可能是您所看到的更多:

#!/usr/bin/env perl

use strict;
use warnings qw[ FATAL all ];
use autodie;

binmode(STDOUT);

my @octet_list = (
    0,  0,  0,  0,  2,
    4,  6,  8,  0,  1,
    3,  0,  5, 20,
);

my $binary = pack("C*", @octet_list);
print STDOUT $binary;

close(STDOUT);

TMTOWTDI

Perl支持多种处理方式,因此您可以选择最习惯的一种方式。如果这是我计划作为学校或工作项目检查的内容,那么我肯定会选择更长,更仔细的版本-
如果我使用的是单行代码,或者至少在shell脚本中添加注释。

您可以在自己的系统上找到Perl的文档。只需输入

% man perl
% man perlrun
% man perlvar
% man perlfunc

等在您的shell提示下。如果要在网上使用漂亮的版本,请从http://perldoc.perl.org获取perl,perlrun,perlvar和perlfunc的联机帮助页。



 类似资料:
  • 下面是一个上传二进制文件的例子,WebService类的代码如下: package service; import java.io.InputStream; import java.io.OutputStream; import java.io.FileOutputStream; import javax.activation.DataHandler; public class 

  • 问题内容: 我正在尝试首次在Linux上安装Haskell平台(我也是一个相当新的Linux用户)。受害者系统是全新的Red Hat系统。并且这里涉及的所有内容都应该是64位。 平台网站上的指示[1]表示我需要ghc7.0.3来增强功能。他们提供了到ghc-7.0.3通用二进制文件的链接来执行此操作。我拿来跑了 按照没有事故的指示(它是二进制文件,因此不需要编译)但是,当我尝试运行ghci时,我得

  • 问题内容: 我正在使用Flash录制音频并将其上传到节点服务器。Flash客户端是jrecorder的变体。当用户完成录制后,将使用POST请求(而不是表单,因为Flash无法创建文件)来上传音频,并将音频ByteArray作为POST请求的数据(请参见此处的更多信息)。 我可以使用下面的代码在Node- land上正确接收文件,但是发出的音频被破坏了,您听不到任何声音。话虽如此,该文件的内容可以

  • 一个插件是一个简单的实现了插件接口的类.Gradle提供的核心插件作为其分布的一部分,因此,你需要做的仅仅是应用上述的插件.然而,非核心二进制插件需要到构建类路径才能应用它们.这可以以多种方式,包括以下方式实现: 定义插件作为构建脚本中内嵌类的声明. 定义插件为在项目中buildSrc目录下的一个源文件.(参见Section 62.4, “Build sources in the buildSrc

  • 问题内容: 与嵌入式设备通信的唯一方法是串行端口。默认情况下,嵌入式Linux使用此端口作为终端。如何禁用此终端并使用串行链接传输二进制数据?我听说过类似rx和tx的命令,但我找不到它们。 我想我可以从/ dev / tty中读取和写入内容,但我想确保没有错误消息或数据流混乱。 问题答案: 您可以使用xmodem之类的应用程序通过任何终端传输文件。是您在终端上说的串行端口,还是内核控制台。 如果您

  • 我可以运行这个程序,但由于某些原因,它会显示/放置随机字符,而不是二进制的初始值,而且我似乎无法将程序从十进制运行回二进制。我该如何改进这些代码。要明确说明它不会将二进制转换为十进制,我将如何将其转换回十进制转换为二进制,如果有一些代码可以帮助我,将不胜感激。