今日、私は自分の電子メールの1つに16進バイトの文字列の形式で返信を受け取りました。
"686170707920333974682068617665206120676f6f64206f6e6521"
そして、文字列をASCIIに相当するものに変換する最も効率的なクリーンな方法を考えていました。質問に答えを追加しますが、これほどエレガントだとは感じませんでした。
ここに反復的な解決策があります
(defun decode-hex-string (hex-string)
(let ((res nil))
(dotimes (i (/ (length hex-string) 2) (apply #'concat (reverse res)))
(let ((hex-byte (substring hex-string (* 2 i) (* 2 (+ i 1)))))
(push (format "%c" (string-to-number hex-byte 16)) res)))))
そしてloop
、副作用の操作を避けたい場合は、 を使用します ((require 'cl)
これを使用するために必要になる場合があります):
(defun decode-hex-string (hex-string)
(apply #'concat
(loop for i from 0 to (- (/ (length hex-string) 2) 1)
for hex-byte = (substring hex-string (* 2 i) (* 2 (+ i 1)))
collect (format "%c" (string-to-number hex-byte 16)))))
一般に、Elisp と Common Lisp では再帰を避けるのが最善です。スタックは十分に大きな入力でキールオーバーし、どちらの言語も末尾再帰を保証しません (使用していませんが、まだ使用しています)。スキームでは、それは別の話です。
ちなみにハッピー39th。
探してここに来る人のために...
Inaimathiの答えを少し詳しく説明すると、選択した領域をデコードされたヘキサに置き換えるコードは次のとおりです。
(defun decode-hex-string (hex-string)
(apply #'concat
(loop for i from 0 to (- (/ (length hex-string) 2) 1)
for hex-byte = (substring hex-string (* 2 i) (* 2 (+ i 1)))
collect (format "%c" (string-to-number hex-byte 16)))))
(defun hex-decode-region (start end)
"Decode a hex string in the selected region."
(interactive "r")
(save-excursion
(let* ((decoded-text
(decode-hex-string
(buffer-substring start end))))
(delete-region start end)
(insert decoded-text))))
(provide 'decode-hex-string)
(provide 'hex-decode-region)
それをファイルに保存してから、Mx load-file を実行します。または、~/emacs.d などに置きます。次に、hex コンテンツと Mx hex-decode-region を含むリージョンを選択します。楽しみ!
これが私のものです。これが特に慣用的またはエレガントであると主張しているわけでもありません。多分少し古い学校。
(defun hex-string-decode (str)
"Decode STR of the form \"4153434949\" to corresponding \"ASCII\"."
(let (decoded sub)
(while (> (length str) 0)
(setq sub (substring str 0 2)
decoded (cons (string-to-number sub 16) decoded)
str (substring str 2) ) )
(when (not (zerop (length str))) (error "residue %s" str))
(mapconcat #'char-to-string (nreverse decoded) "") ) )
最初は、Elisp でなければならないという要件が見当たらなかったので、対話的に行いました。以下のコードは、私の対話的な手順に従います。
(defun decode-hex-string (hex-string)
(with-temp-buffer
(insert-char 32 (/ (length hex-string) 2))
(beginning-of-buffer)
(hexl-mode)
(hexl-insert-hex-string hex-string 1)
(hexl-mode-exit)
(buffer-string)))
これは私が思いついた解決策で、少し醜いと思いました:
(defun decode-hex-string(string)
"Decode a hex string into ASCII"
(let* ((hex-byte (substring string 0 2))
(rest (substring string 2))
(rest-as-string (if (> (length rest) 2)
(decode-hex-string rest)
"")))
(format "%c%s" (string-to-number hex-byte 16) rest-as-string)))