2011-11-09 112 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已經很長的行中增加更多。 –

相關問題