簡體   English   中英

如何使用elisp將十六進制字符串轉換為ASCII?

[英]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-numberstring-to-listconcat ,以及dash.el函數-partitiondash.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM