
深刻な破損したSqliteファイルがあります。すべてをSQLファイルにダンプして新しいファイルにロードする一般的な方法は機能しませんが、16進エディタを使用すると回復する必要があるデータがあることがわかります。
このパターンに出会いました。
vimはASCII文字のみを表示し、別のバイトをバイナリデータとして扱うことはできますか?
viに印刷できない文字を16進数で表示するようにします。
すごいですね、お知らせします。
14>>07>>テイスティ・マクタイソン氏[Eメール保護]
しかし、表示しながらファイルに書き込む方法はありますか?
したがって、viがバッファに<14>という16進値で表示することは、実際にそれをテキストファイルの対応する文字に変更します。
viで正規表現の検索と置換を行うことでこれを実行できますが、印刷できない各文字に対して一度に1つずつ実行する必要があります。これはかなり大きなファイルです。
後で<14> <07>を16ビット整数として扱う予定ですが、まずそれを実際の文字としてテキストファイルに入れることができるはずです。
事前にありがとう
答え1
xxd
付属のコンテンツを表示して、vim
列に16進データと印刷可能文字をダンプできます。 16進数を編集する場合は、データを再プッシュしてxxd -r
2進数に戻すことができます。
ただし、最終目標を見ると、より強力なものが必要になる場合がありますperl
。たとえば、私はこれの専門家ではありませんが、次のことが役に立ちます。
#!/usr/bin/perl
# https://unix.stackexchange.com/a/452784/119298
use strict;
sub fn{
my ($ch,$ch2,$rest) = @_;
return sprintf("%5u",(ord($ch)<<8)|ord($ch2)).$rest;
}
my $data = join("",<>);
$data =~ s/(.)(.)([a-zA-Z][ -~]{10,})/fn($1,$2,$3)/ge;
print $data;
stdinのすべてのデータを変数として読み取り、ランダムな$data
2s/.../.../g
バイト文字とアルファベット文字(azとAZの範囲)、その後に10文字以上の印刷可能文字(チルダまでの範囲、C言語環境の仮定)をペアで連結します。これらの部分は()
3つの別々の部分に分割されてキャプチャされ、関数呼び出しに置き換えられますfn
。e
結局これが意味するところです。
この関数は、単に整数に変換され、変更されていない3番目の引数に関連付けられた2バイトの文字列印刷を返します。
助けるためにあなたが望むことをするより簡単なバージョンがあります。印刷されない文字を<..>
。
my $data = join("",<>);
$data =~ s/([^ -~\n])/sprintf("<%02x>",ord($1))/ge;
print $data;
^
ここのパターンは比較的簡単です。つまり、意味のある印刷できない文字(および改行文字)の範囲です。いいえ。単純なsqliteファイルを見ると、テキストデータの直前の文字が通常印刷可能な文字であることがわかりました。だから、文字開始文字をテストするパターンを使用しましたが、より良い経験的な方法を使用することをお勧めします。
答え2
以下は、0x00 - 0x20の範囲の印刷されていない文字(CR、LF、タブ、スペースを除く)を置き換えます。#xDD#
ここでDD
文字の16進数表現は次のとおりです(ありがとうございます)この問題明確に定義された範囲の場合):
sed $( (seq 0 8; seq 11 12; seq 14 31) | awk '{ printf("s/\\x%02x/#x%02x#/;", $0, $0) }' )
私はseq
置き換える文字範囲を生成し、awk
パターンを生成するために使用しますsed
。後者は実際の置換を行います。
次のようにテストできます。
seq 0 32 | awk '{$0 =$0 sprintf("%c",$0)} 1' | sed $( (seq 0 8; seq 11 12; seq 14 31) | awk '{ printf("s/\\x%02x/#x%02x#/;", $0, $0) }' )
FWIWクエリでこのコンテンツを見つけた人のために、アルパインドッカー画像(私の破損したファイルを処理したい場所)はsed
NULL文字が好きではないので、次のように修正する必要がありました。
sed $( (seq 1 8; seq 11 12; seq 14 31) | awk '{ printf("s/\\x%02x/#x%02x#/;", $0, $0) }' ) | tr '\0' '\1' | sed 's/\x01/#x00#/'