根据模式将一个文件拆分为多个文件

jay*_*ngh 18 bash awk split sed

我有一个二进制文件,我使用hexdump和几个awk和sed命令转换为常规文件.输出文件看起来像这样 -

$cat temp
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e5820000000000000000000
000000087d3f513000000000000000000000000000000000001001001010f000000000026 
58783100b354c52658783100b43d3d0000ad6413400103231665f301010b9130194899f2f
fffffffffff02007c00dc015800a040402802f1d5b2b8ca5674504f433031000000000004
6363070000000000000000000000000065450000b4fb6b4000393d3d1116cdcc57e58287d
3f55285a1084b
Run Code Online (Sandbox Code Playgroud)

临时文件很少有眼睛捕捉器(3d3d),它们不经常重复.他们有点表示新二进制记录的开始.我需要根据那些吸引眼球来分割文件.

我想要的输出是有多个文件(根据我的临时文件中的引人注目的数量).

所以我的输出看起来像这样 -

$cat temp1
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e582000000000000000
0000000000087d3f513000000000000000000000000000000000001001001010f00000000
002658783100b354c52658783100b4

$cat temp2
3d3d0000ad6413400103231665f301010b9130194899f2ffffffffffff02007c00dc0
15800a040402802f1d5b2b8ca5674504f4330310000000000046363070000000000000000
000000000065450000b4fb6b400039

$cat temp3
3d3d1116cdcc57e58287d3f55285a1084b
Run Code Online (Sandbox Code Playgroud)

Mic*_*ber 18

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

cat temp |
  awk -v RS="3d3d" '{ print $0 > "temp" NR }' 
Run Code Online (Sandbox Code Playgroud)

示例文本以引人注目的方式开始3d3d,因此temp1将是一个空文件.此外,引人注目本身不会出现在临时文件的开头,如问题中的临时文件所示.最后,如果有很多记录,您可能会遇到打开文件的系统限制.一些轻微的并发症将使它更接近您想要的并使其更安全:

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

  • @ZsoltBotykai很清楚这一点,虽然不相信它说的是适当的修辞论述.您可能希望阅读其他视图,例如*Classic Shell Scripting*(Robbins and Beebe,2005). (4认同)
  • 正如所讨论的那样,@ ZsoltBotykai RS在输出中.而cat并非无用:它提供了数据生成和处理之间的逻辑分离.因此,`cat temp`代表在awk阶段之前进行的任何转换,同时避免使用awk向已经很长的行添加更多. (2认同)

rob*_*off 15

#!/usr/bin/perl

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

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


pot*_*ong 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
Run Code Online (Sandbox Code Playgroud)

编辑:

如果源文件中有换行符,您可以先使用它们删除它们tr -d '\n' <temp,然后通过上面的sed命令管道输出.如果你想保留它们,那么:

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

应该做的伎俩