Regular-Expression

用十六進制數值替換不可列印的字元

  • March 30, 2020

我有一個嚴重損壞的 Sqlite 文件將所有內容轉儲到 sql 文件並將其載入到新文件中的常用技巧不起作用,但是使用十六進制編輯器我可以看到我需要恢復的數據在那裡

我遇到了這種模式

vim 可以只顯示 ASCII 字元,而將其他字節視為二進制數據嗎?

vi 將不可列印的字元顯示為十六進制

這很棒,會告訴我

‹14›‹07› Testy McTesterson 先生 me@example.com

但是有沒有在顯示時將其寫入文件?

因此,將 vi 在其緩衝區中顯示為 ‹14› 的十六進制值實際更改為文本文件中的那些字元

我可以在 vi 中做一個正則表達式搜尋替換來做,但是我必須一次為每個不可列印的字元做一個,這是一個非常大的文件

稍後,我計劃將‹14›‹07›處理成它應該表示的16位整數,但首先我需要能夠將這些作為真實字元放入文本文件中

提前謝謝了

您可能會查看xxd附帶的哪些vim數據,並以十六進制格式轉儲數據,並在列中轉儲可列印字元。如果您編輯十六進制,您可以將數據推回xxd -r以將其轉換回二進制。

然而,看看你的最終目標,你可能需要更強大的東西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;

它將標準輸入中的所有數據讀入變數$data,然後對s/.../.../g由任意 2 個字節後跟一個字母字元(範圍 az 和 AZ)、後跟 10 個或更多可列印字元(在範圍空間到波浪號,並假設 C 語言環境)。這些部分通過 using 被擷取()為 3 個單獨的部分,並由 function 的呼叫替換fn。這就是e最後的意思。

該函式只返回一個字元串列印,將 2 個字節轉換為整數,並與第三個未更改的參數連接。

為了提供幫助,這裡有一個更簡單的版本,它只做你想要的,將非列印字元替換為<..>.

my $data = join("",<>);
$data =~ s/([^ -~\n])/sprintf("<%02x>",ord($1))/ge;
print $data;

這裡的模式更簡單,即不可列印字元(和換行符)的範圍,^意思是not。在查看一個簡單的 sqlite 文件時,我發現文本數據之前的字元通常是可列印字元。這就是為什麼我使用了一個測試字母起始字元的模式,但您可能需要使用更好的啟發式方法。

引用自:https://unix.stackexchange.com/questions/452766