在elisp中,如何将"var = value \n ..."字符串计算为同名的lisp变量?

Pet*_*r.O 3 emacs elisp

mplayer工具(midentify)输出"shell-ready"行,用于由bash/sh /任何解释器进行评估.

如何将这些var-names作为emacs中的elisp var-names分配给相应的值?数据以字符串形式(通过shell-command-to-string)

这是数据

ID_AUDIO_ID=0
ID_FILENAME=/home/axiom/abc.wav
ID_DEMUXER=audio
ID_AUDIO_FORMAT=1
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=0
ID_AUDIO_NCH=1
ID_LENGTH=3207.00
ID_SEEKABLE=1
ID_CHAPTERS=0
ID_AUDIO_BITRATE=512000
ID_AUDIO_RATE=32000
ID_AUDIO_NCH=1
ID_AUDIO_CODEC=pcm
ID_EXIT=EOF
Run Code Online (Sandbox Code Playgroud)

Sea*_*ean 5

这是一个例程,它接受包含midentify输出的字符串,并返回键值对的关联列表(这比不受威胁地设置Emacs变量更安全).它还具有将数值解析为实际数字的优点:

(require 'cl)  ; for "loop"
(defun midentify-output-to-alist (str)
  (setq str (replace-regexp-in-string "\n+" "\n" str))
  (setq str (replace-regexp-in-string "\n+\\'" "" str))
  (loop for index = 0 then (match-end 0)
        while (string-match "^\\(?:\\([A-Z_]+\\)=\\(?:\\([0-9]+\\(?:\\.[0-9]+\\)?\\)\\|\\(.*\\)\\)\\|\\(.*\\)\\)\n?" str index)
        if (match-string 4 str)
        do (error "Invalid line: %s" (match-string 4 str))
        collect (cons (match-string 1 str)
                      (if (match-string 2 str)
                          (string-to-number (match-string 2 str))
                        (match-string 3 str)))))
Run Code Online (Sandbox Code Playgroud)

你会像这样使用这个函数:

(setq alist (midentify-output-to-alist my-output))
(if (assoc "ID_LENGTH" alist)
    (setq id-length (cdr (assoc "ID_LENGTH" alist)))
  (error "Didn't find an ID_LENGTH!"))
Run Code Online (Sandbox Code Playgroud)

编辑:修改功能来正确处理空白行和尾随换行符.

regexp确实是一头野兽; Emacs regexp因其易于眼睛而闻名.稍微分解一下:

  • 最外层的图案是^(?:valid-line)|(.*).它尝试匹配有效行,或者匹配.*match-group 4 中的整行(the ).如果(match-group 4 str)不匹配nil,则表示遇到了无效行,并引发错误.
  • valid-line(word)=(?:(number)|(.*)).如果这匹配,则名称 - 值对的名称部分在匹配字符串1中,如果该行的其余部分与数字匹配,则该数字在匹配字符串2中,否则该行的其余部分为在match-string 3中.