[英]How do I convert a string of hex into ASCII using elisp?
今天我收到了一封以十六進制字節為單位的電子郵件的回復:
"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中遞歸; 你的堆棧將通過足夠大的輸入進行管理,並且兩種語言都不能保證尾遞歸(你沒有使用,但仍然如此)。 在Scheme中,這是一個不同的故事。
順便說一句,快樂39號。
如果您使用Magnar Sveen的dash.el
列表API(您應該),請嘗試:
(concat (--map (string-to-number (concat it) 16) (-partition 2 (string-to-list "686170707920333974682068617665206120676f6f64206f6e6521"))))
該解決方案使用Emacs函數string-to-number
, string-to-list
和concat
,以及dash.el
函數-partition
和dash.el
version of -map
。 concat
的好處在於它不僅連接字符串,還連接字符列表或向量。 我們可以使用->>
threading宏重寫這段代碼。 它接受第一個參數的結果,然后將它應用於第二個,第三個等參數,就像Unix管道一樣 。
(->> (string-to-list "686170707920333974682068617665206120676f6f64206f6e6521")
(-partition 2)
(--map (string-to-number (concat it) 16))
concat)
這是我的。 我並不是說這是特別慣用或優雅的。 也許有點老了。
(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) "") ) )
對於那些來這里尋找...
在Inaimathi的回答中詳細說明,這里是用解碼的hexa替換所選區域的代碼:
(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加載文件。 或者穿上〜/ emacs.d,或其他什么。 然后選擇具有hexa內容和Mx十六進制解碼區域的區域。 請享用!
這是我提出的解決方案讓我覺得有點難看:
(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)))
起初我沒有看到它必須是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)))
建立Inaimathi和Shrein提供的答案,我還添加了編碼功能。 以下是字符串和區域參數的編碼和解碼實現:
;; ASCII-HEX converion
(defun my/hex-decode-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)))))
(defun my/hex-encode-string (ascii-string)
(let ((res nil))
(dotimes (i (length ascii-string) (apply #'concat (reverse res)))
(let ((ascii-char (substring ascii-string i (+ i 1))))
(push (format "%x" (string-to-char ascii-char)) res)))))
(defun my/hex-decode-region (start end)
"Decode a hex string in the selected region."
(interactive "r")
(save-excursion
(let* ((decoded-text
(my/hex-decode-string
(buffer-substring start end))))
(delete-region start end)
(insert decoded-text))))
(defun my/hex-encode-region (start end)
"Encode a hex string in the selected region."
(interactive "r")
(save-excursion
(let* ((encoded-text
(my/hex-encode-string
(buffer-substring start end))))
(delete-region start end)
(insert encoded-text))))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.