2011-11-09 13 views
16

私は、hexdumpとawkとsedコマンドを使用して普通のファイルに変換するバイナリファイルを持っています。一時ファイルは、多くの場合、それを繰り返していないいくつかのアイキャッチャー(3d3d)がパターンに基づいて1つのファイルを複数のファイルに分割する

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

- 出力ファイルは次のようになります。彼らはちょっと新しいバイナリレコードの始まりを示しています。私はそれらのアイキャッチャーに基づいてファイルを分割する必要があります。

私の望む出力は、(テンポラリファイル内のアイキャッチャーの数に基づいて)複数のファイルを持つことです。

だから私の出力は次のようになります - それはあなたのtempファイル内の1行だかどうかは異なり

$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

を。独自のファイルへのその後

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 

EDIT:

もしそこソースファイル内の改行で、最初にを使用して削除できますを入力し、出力を上記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、あなたはドンそれのために 'cat'が必要です。また、単一行入力の場合は、最初のレコードのみを取得します。そして、出力は元の 'RS'も欠けているでしょう。 'echo '3d3dsomething3d3danything' | awk 'BEGIN {RS = "3d3d"} {print}' 'は'何か 'しか出力しません。 –

+1

または私は間違っていた。ソリューションの唯一の問題は、出力に「RS」がないことです。 (そして 'cat 'の無用な使用) –

+2

@ZsoltBotykai RSは議論のとおり出力されます。また、猫は無駄ではありません。データの生成と処理の間に論理的な分離があります。したがって、 'cat temp 'はawkステージの前にどのような変換が起こっても、awkを使ってすでに長い行にさらに多くの行を追加することを避けています。 –