2011-11-09 106 views
16

我有一个二进制文件,我使用hexdump和几个awk和sed命令将其转换为常规文件。输出文件看起来像这样 -根据模式将一个文件拆分为多个文件

$cat temp 
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e5820000000000000000000 
000000087d3f513000000000000000000000000000000000001001001010f000000000026 
58783100b354c52658783100b43d3d0000ad6413400103231665f301010b9130194899f2f 
fffffffffff02007c00dc015800a040402802f1d5b2b8ca5674504f433031000000000004 
6363070000000000000000000000000065450000b4fb6b4000393d3d1116cdcc57e58287d 
3f55285a1084b 

临时文件有几个眼球捕手(3d3d),这不经常重复。它们表示新的二进制记录的开始。我需要根据那些眼睛捕捉者来分割文件。

我希望的输出是有多个文件(根据我的临时文件中的eyecatchers的数量)。

所以我的输出将是这个样子 -

$cat temp1 
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e582000000000000000 
0000000000087d3f513000000000000000000000000000000000001001001010f00000000 
002658783100b354c52658783100b4 

$cat temp2 
3d3d0000ad6413400103231665f301010b9130194899f2ffffffffffff02007c00dc0 
15800a040402802f1d5b2b8ca5674504f4330310000000000046363070000000000000000 
000000000065450000b4fb6b400039 

$cat temp3 
3d3d1116cdcc57e58287d3f55285a1084b 

回答

14
#!/usr/bin/perl 

undef $/; 
$_ = <>; 
$n = 0; 

for $match (split(/(?=3d3d)/)) { 
     open(O, '>temp' . ++$n); 
     print O $match; 
     close(O); 
} 
+0

感谢这个伟大工程,使之运行在所有的临时文件,我可以打电话给我的解析器脚本中此脚本运行解析器代码之前。 –

+0

我应该选择哪些书来学习Perl。我是UNIX新手,最近开始学习bash,sed和awk。 –

+3

可能* [学习Perl](http://www.amazon.com/dp/1449303587)*。 –

-1

这取决于它是否在你的temp文件或不是单行线。

sed 's/\(.\)\(3d3d\)/\1#\2/g' FILE | awk -F "#" '{ for (i=1; i++; i<=NF) { print $i > "temp" i } }' 

第一sed插入一个#作为字段/记录分隔符,然后awk分裂的#并打印每一个“场”,以自己的文件:但假设,如果它是一个单一的线,你可以走了。

如果输入文件已经被分割在3d3d那么你就可以去:

awk '/^3d3d/ { i++ } { print > "temp" i }' temp 

HTH

5

这可能会实现:

# sed 's/3d3d/\n&/2g' temp | split -dl1 - temp 
# ls 
temp temp00 temp01 temp02 
# cat temp00 
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e5820000000000000000000000000087d3f513000000000000000000000000000000000001001001010f000000000026 58783100b354c52658783100b4 
# cat temp01 
3d3d0000ad6413400103231665f301010b9130194899f2ffffffffffff02007c00dc015800a040402802f1d5b2b8ca5674504f4330310000000000046363070000000000000000000000000065450000b4fb6b400039 
# cat temp02 
3d3d1116cdcc57e58287d3f55285a1084b 

编辑:

如果有是源文件中的换行符,您可以使用先将其移除,然后通过上述sed命令管道输出。然而,如果你希望保留他们,那么:

sed 's/3d3d/\n&/g;s/^\n\(3d3d\)/\1/' temp |csplit -zf temp - '/^3d3d/' {*} 

应该做的伎俩

16

awkRS变量是这个漂亮的,允许你定义记录分隔符。因此,您只需要在自己的临时文件中捕获每条记录。最简单的版本是:

cat temp | 
    awk -v RS="3d3d" '{ print $0 > "temp" NR }' 

示例文本与值得一看3d3d启动,因此temp1中会是一个空文件。此外,引人注目的本身不会出现在临时文件的开头,正如问题中的临时文件所示。最后,如果有很多记录,则可能会遇到打开文件的系统限制。一些轻微的并发症会使其更接近你想要什么,并使其更安全:

cat temp | 
    awk -v RS="3d3d" 'NR > 1 { print RS $0 > "temp" (NR-1); close("temp" (NR-1)) }' 
+1

Khm,你不用为此,不需要“猫”。如果是单行输入,则只会获得第一条记录。输出也会错过原来的'RS'。 '回声'3d3dsomething3d3danything'| awk'BEGIN {RS =“3d3d”} {print}“'只会输出”something“。 –

+1

或者我错了。您的解决方案唯一的问题是缺少输出中的RS。 (以及无用的'cat'。) –

+2

@ZsoltBotykai RS在输出中,正如讨论的那样。猫不是无用的:它提供了数据生成和处理之间的逻辑分离。因此,'cat temp'代表在awk阶段之前进行的任何转换,同时避免在awk已经很长的行中增加更多。 –

相关问题