今天我收到了一封以十六进制字节为单位的电子邮件回复:
"686170707920333974682068617665206120676f6f64206f6e6521"
我正在考虑将字符串转换为ASCII等效的最有效的干净方法。我会在问题中添加我的答案,但我觉得它并不像它本来那样优雅。
答案 0 :(得分:8)
这是一个迭代解决方案
(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中,这是一个不同的故事。
顺便提一下,Happy 39th。
答案 1 :(得分:4)
如果您使用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
和-map
的照应版本。 concat
的好处在于它不仅连接字符串,还连接字符列表或向量。我们可以使用->>
线程宏重写此代码。它接受第一个参数的结果,然后将其应用于第二个,第三个等参数,就像Unix pipe一样。
(->> (string-to-list "686170707920333974682068617665206120676f6f64206f6e6521")
(-partition 2)
(--map (string-to-number (concat it) 16))
concat)
答案 2 :(得分:1)
这是我的。我并不是说这是特别惯用或优雅的。也许有点老了。
(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) "") ) )
答案 3 :(得分:1)
对于那些来这里寻找......
在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)
将其保存在文件中,然后保存为M-x加载文件。或者穿上〜/ emacs.d,或其他什么。然后选择具有hexa内容和M-x十六进制解码区域的区域。享受!
答案 4 :(得分:0)
这是我提出的解决方案让我觉得有点难看:
(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)))
答案 5 :(得分:0)
起初我没有看到它必须是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)))
答案 6 :(得分:0)
建立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))))