hexl-modeでバイトシーケンスを検索する方法


7

でバイトシーケンスを検索し、hexl-mode場合によってはそれを強調表示することは可能ですか?

たとえば、以下のファイルでバイトシーケンスを検索しますf9beb4d9isearch元のファイルではなく、バッファ内のプレゼンテーションを検索するため、機能しません。

00000000: f9be b4d9 1d01 0000 0100 0000 0000 0000  ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 3ba3 edfd  ............;...
00000030: 7a7b 12b2 7ac7 2c3e 6776 8f61 7fc8 1bc3  z{..z.,>gv.a....
00000040: 888a 5132 3a9f b8aa 4b1e 5e4a 29ab 5f49  ..Q2:...K.^J)._I
00000050: ffff 001d 1dac 2b7c 0101 0000 0001 0000  ......+|........
00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................

例を挙げて「バイト列を探す」の意味を明確にしてください。
Stefan

私が考える「バイトシーケンスを検索」@Stefan「検索で交換する必要があるため、バイト配列」。OPはこれを修正する必要があります。修正されたバージョンが正しい場合は、hexlバッファーでの「バイトシーケンスの検索」の意味がかなり明確です。hexlバッファーが実際には元のバッファーのバイトシーケンスを表すことを考慮する必要があります。ユーザーはhexlがどのように機能するか、およびhexlバッファー内のバイトシーケンスと元のバイトシーケンス内のバイトシーケンスに微妙な違いがあることを知る必要はありません。
トビアス

1
主な質問は、彼が探しているシーケンスをどのように指定するつもりなのかです。
Stefan

質問が明確になったことを願っています。
gdkrmr 2018

@Stefan、文字列と16進表記の両方を検索できる場合のボーナスポイント:-)私は、バイトの16進表記のみに関心があります。
gdkrmr 2018

回答:


2

あなたが使用する場合nhexl-mode(あなたの隣のGNU ELPAアーカイブから入手可能)、あなたはそれを行うことができC-s f9beb4d9、コードで4バイトのシーケンスを検索しますf9 be b4 d9(もちろん8バイトのテキストf9beb4d9、そしてに含まf9beb4d9れるアドレスのバイトも検索します) 16進表記)。


このおかげで動作しますが、大きなファイルでのパフォーマンスはひどいです。
gdkrmr 2018

1
@gdkrmr:nhexl-modeを開発した動機の1つは、大きなファイルでhexl-modeのパフォーマンスの問題を回避することでした。しかし、正直なところ、パフォーマンスの問題が発生していることにまったく驚かされていません。M-x report-emacs-bugできるだけ多くの詳細を提供して報告してください(ファイルの内容によってパフォーマンスが大幅に影響を受ける可能性があるため、サンプルの大きなファイルへのURLも役立つ場合があります)。
Stefan

1
こんにちはステファン、私はバイナリを検索し、アドレスをhexlバッファの位置に変換しています。パフォーマンスの問題はないようです。多分それはhexlまたはnhexlの代替ですか?git-repository:github.com/TobiasZawada/hexl-isearchで問題をすでに修正しました。
トビアス

2

次のlispコードは、「Hexl Isearch Mode」というエントリを「Hexl」メニューに追加します。

そのメニュー項目は、マイナーモードを(非)アクティブにしますhexl-isearch-mode。このモードをアクティブisearchにすると、hexlバッファーの代わりにバイナリデータで検索されます。

検索文字列はで読み取られreadます。したがって、lisp文字列のすべてのエスケープシーケンスは機能します。例として、dos line endを検索\x0a\x0dまたは検索できます\^M\n

コードは完璧ではありません。

  1. ELF\x01ファイルの先頭にのみ出現する文字列を検索するとします。さらに、ELf\x00後でバイナリに文字列があると仮定します。次に、ELF\x0Emacsと入力して到着すると、後で一致するものが見つかります。入力を続けると、ELF\x01Emacsは、その文字列がすでに到着しているため、その文字列の出現はないと考えELF\x0ますELF\x01。このような場合、重複検索を行う価値があります。(この問題は、パッケージのgitバージョンですでに修正されています。)

  2. 右側の文字列表現ではなく、バイトシーケンスのみがhexlバッファーで正しく強調表示されます。

  3. 検索文字列がhexlバッファーの2行にまたがっている場合、行の最後の文字列表現と行の先頭のアドレスも強調表示されます。これは、それらが一致に属しているためではなく、バイトシーケンスを強調表示するときに邪魔になるためです。

(require 'hexl)

(defvar-local hexl-isearch-raw-buffer nil
  "Buffer with the dehexlified content of the hexl buffer for hexl-isearch-mode.
This variable is set in the original hexl-mode buffer.")

(defvar-local hexl-isearch-original-buffer nil
  "This variable is set in the buffer with the dehexlified content.
It points to the corresponding hexl buffer.")

(defun hexl-address (position)
  "Return address of hexl buffer POSITION."
  (save-excursion
    (goto-char position)
    (hexl-current-address)))

(defun hexl-isearch-startup ()
  "Prepare hexl buffer for `hexl-isearch'."
  (let ((original-buf (current-buffer)))
    (setq-local hexl-isearch-raw-buffer (generate-new-buffer " hexl"))
    (setq-local isearch-search-fun-function (lambda () #'hexl-isearch-fun))
    (with-current-buffer hexl-isearch-raw-buffer
      (set-buffer-multibyte nil)
      (setq-local hexl-isearch-original-buffer original-buf)
      (insert-buffer-substring original-buf 1 (buffer-size original-buf))
      (dehexlify-buffer))))

(defun hexl-isearch-end ()
  "Cleanup after `hexl-isearch'."
  (let ((isearch-raw-buffer hexl-isearch-raw-buffer))
    (setq-local hexl-isearch-raw-buffer nil)
    (when (buffer-live-p isearch-raw-buffer)
      (kill-buffer isearch-raw-buffer))))

(defun hexl-isearch-fun (string &optional bound noerror count)
  "Search for byte sequence of STRING in hexl buffer.
The arguments BOUND and NOERROR work like in `search-forward'."
  (when bound (setq bound (1+ (hexl-address bound))))
  (setq string (read (concat "\"" string "\"")))
  (let ((point (1+ (hexl-current-address)))
    match-data)
    (with-current-buffer hexl-isearch-raw-buffer
      (goto-char point)
      (setq point (funcall (if isearch-forward #'re-search-forward #'re-search-backward)
               (if isearch-regexp
                   string
                 (regexp-quote string))
               bound noerror count))
      (setq match-data (match-data t nil t)))
    (when point
      (prog1
      (hexl-goto-address (1- point))
    (set-match-data
     (mapcar (lambda (el)
           (if (integerp el)
               (hexl-address-to-marker (1- el))
             el))
         match-data))))))

(define-minor-mode hexl-isearch-mode
  "Search for binary string with isearch in hexl buffer."
  :lighter " hi"
  (if hexl-isearch-mode
      (progn
    (setq-local isearch-search-fun-function #'hexl-isearch-fun)
    (add-hook 'isearch-mode-hook #'hexl-isearch-startup t t)
    (add-hook 'isearch-mode-end-hook #'hexl-isearch-end t t))
    (setq-local isearch-search-fun-function #'isearch-search-fun-default)
    (remove-hook 'isearch-mode-hook #'hexl-isearch-startup t)
    (remove-hook 'isearch-mode-end-hook #'hexl-isearch-end t)))

(easy-menu-add-item hexl-mode-map '(menu-bar Hexl)
            ["Hexl Isearch Mode" (if hexl-isearch-mode (hexl-isearch-mode -1) (hexl-isearch-mode)) :style toggle :selected hexl-isearch-mode] "Go to address")

あなたの作品もそうです、そして大きなファイルではるかに高性能です!
gdkrmr 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.