Hexdumpといくつかのawkおよびsedコマンドを使用して通常のファイルに変換するバイナリファイルがあります。出力ファイルは次のようになります-
$cat temp
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e5820000000000000000000
000000087d3f513000000000000000000000000000000000001001001010f000000000026
58783100b354c52658783100b43d3d0000ad6413400103231665f301010b9130194899f2f
fffffffffff02007c00dc015800a040402802f1d5b2b8ca5674504f433031000000000004
6363070000000000000000000000000065450000b4fb6b4000393d3d1116cdcc57e58287d
3f55285a1084b
一時ファイルには、それほど頻繁に繰り返されない目印(3d3d)がほとんどありません。彼らはちょっと新しいバイナリレコードの始まりを示します。それらの目印に基づいてファイルを分割する必要があります。
私の望ましい出力は、(一時ファイルの目印の数に基づいて)複数のファイルを持つことです。
だから私の出力は次のようになります-
$cat temp1
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e582000000000000000
0000000000087d3f513000000000000000000000000000000000001001001010f00000000
002658783100b354c52658783100b4
$cat temp2
3d3d0000ad6413400103231665f301010b9130194899f2ffffffffffff02007c00dc0
15800a040402802f1d5b2b8ca5674504f4330310000000000046363070000000000000000
000000000065450000b4fb6b400039
$cat temp3
3d3d1116cdcc57e58287d3f55285a1084b
#!/usr/bin/Perl
undef $/;
$_ = <>;
$n = 0;
for $match (split(/(?=3d3d)/)) {
open(O, '>temp' . ++$n);
print O $match;
close(O);
}
RS
のawk
変数は、これに最適で、レコードセパレータを定義できます。したがって、各レコードを独自の一時ファイルにキャプチャする必要があるだけです。最も単純なバージョンは次のとおりです。
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)) }'
これはうまくいくかもしれません:
# sed 's/3d3d/\n&/2g' temp | split -dl1 - temp
# ls
temp temp00 temp01 temp02
# cat temp00
3d3d01f87347545002f1d5b2be4ee4d700010100018000cc57e5820000000000000000000000000087d3f513000000000000000000000000000000000001001001010f000000000026 58783100b354c52658783100b4
# cat temp01
3d3d0000ad6413400103231665f301010b9130194899f2ffffffffffff02007c00dc015800a040402802f1d5b2b8ca5674504f4330310000000000046363070000000000000000000000000065450000b4fb6b400039
# cat temp02
3d3d1116cdcc57e58287d3f55285a1084b
編集:
ソースファイルに改行がある場合は、最初にtr -d '\n' <temp
を使用してそれらを削除し、次に上記のsed
コマンドを介して出力をパイプ処理できます。ただし、保存したい場合は、次のようにします。
sed 's/3d3d/\n&/g;s/^\n\(3d3d\)/\1/' temp |csplit -zf temp - '/^3d3d/' {*}
トリックを行う必要があります
ニースawk -v RS="pattern"
トリックが機能しない場合。これが私が働いたことです:
この例の場合、concatted.txt
filename=foo bar
foo bar line1
foo bar line2
filename=baz qux
baz qux line1
baz qux line2
このコマンドを使用します(コメントを削除して失敗しないようにします)
# cat: useless use of cat ^__^;
# tr: replace all newlines with delimiter1 (which must not be in concatted.txt) so we have one line of all the next
# sed: replace file start pattern with delimiter2 (which must not be in concatted.txt) so we know where to split out each file
# tr: replace delimiter2 with NULL character since sed can't do it
# xargs: split giant single-line input on NULL character and pass 1 line (= 1 file) at a time to echo into the pipe
# sed: get all but last line (same as head -n -1) because there's an extra since concatted-file.txt ends in a NULL character.
# awk: does a bunch of stuff as the final command. Remember it's getting a single line to work with.
# {replace all delimiter1s in file with newlines (in place)}
# {match regex (sets RSTART and RLENGTH) then set filename to regex match (might end at delimiter1). Note in this case the number 9 is the length of "filename=" and the 2 removes the "§" }
# {write file to filename and close the file (to avoid "too many files open" error)}
cat ../concatted-file.txt \
| tr '\n' '§' \
| sed 's/filename=/∂filename=/g' \
| tr '∂' '\0' \
| xargs -t -0 -n1 echo \
| sed \$d \
| awk '{match($0, /filename=[^§]+§/)} {filename=substr($0, RSTART+9, RLENGTH-9-2)".txt"} {gsub(/§/, "\n", $0)} {print $0 > filename; close(filename)}'
結果は、それぞれfoo bar.txt
およびbaz qux.txt
という名前の2つのファイルになります。
filename=foo bar
foo bar line1
foo bar line2
filename=baz qux
baz qux line1
baz qux line2
お役に立てれば!