org babel 何如保留 前缀 0?

有人知道怎么保留 ID 列的 前缀 0 吗?

比如, 字符 00001 而非 数值 1

#+name: TBL
|   id | name   | age |
|------|--------|-----|
| 0001 | Apollo |  16 |
| 0002 | Bmw    |  16 |

#+BEGIN_SRC python :results output :var tbl=TBL
  print(tbl)
#+END_SRC
#+RESULTS:
: [[1, 'Apollo', 16], [2, 'Bmw', 16]]

‘0001’

或是

修改python中的代码

这是 org-babel-expand-src-block 的解析机制的问题, 是 org-babel 的本来就是这样设计的 (但是很讨厌这样的设计). 修改 python 代码, 不解决本质问题.

更进一步看,是 org-babel-read-table 在把看起来像数字的数据转化成了「数字」类型,估计是为了方便,

根据 org-babel-read 的 docstring,一个 Work-around 是添加引号:

#+name: tbl
| "001" |
| "002" |
| "003" |

#+begin_src python :var data=tbl :results output
print(data)
#+end_src

#+RESULTS:
: [['001'], ['002'], ['003']]

手动编辑加引号, 不是好的方案.

所以叫做 Work-around。如果期待解决方案,得向开发者求助,提交一个 Bug 或 Feature Request。

不改 python,不加引号,那只能改 org-mode 了:

(defun my/org-babel--string-to-number (string)
  "If STRING represents a number return its value.
Otherwise return nil."
  (and (string-match-p "\\`-?\\([0-9]\\|\\([1-9]\\|[0-9]*\\.\\)[0-9]*\\)\\'" string)
       (string-to-number string)))

(advice-add 'org-babel--string-to-number :override 'my/org-babel--string-to-number)

;; test
;; (mapcar (lambda (string)
;;           (and (my/org-babel--string-to-number string)
;;                t))
;;         '("001" "0.1" "00.1" "100" "100.1"))
;; => (nil t t t t)

修改之后所有 0001 形式的数据都当作字符处理了:

#+name: TBL
|   id | name   | age |
|------|--------|-----|
| 0001 | Apollo |  16 |
| 0002 | Bmw    |  16 |

#+BEGIN_SRC emacs-lisp :results value :var tbl=TBL
(format "%S" tbl)
#+END_SRC

#+RESULTS:
: (("0001" "Apollo" 16) ("0002" "Bmw" 16))

已经习惯 org 原有处理方式的人看到结果可能会觉得有点奇怪。如果想要更加无害,可以改为自定义参数的方式,例如 :format ("id" . string)。别人看到这个参数,大概能明白它的意思。


APPEND 2018-10-10 16.59.34

这个函数存在 bug,待完善:

(my/org-babel--string-to-number "0") ;; =>  nil(期望值 0)
(my/org-babel--string-to-number "1") ;; =>  1

UPDATE 2018-10-10 17.45.59

增加了对一位数字的匹配,现在应该没问题了:

(my/org-babel--string-to-number "0")  ;; =>  0(期望值 0)
(my/org-babel--string-to-number "1")  ;; =>  1
2 个赞

:+1:

  • 第一种方法, 很好的解决了我的问题.
  • 第二种方法, 我org-mode 的功底不深, 不是很明白. :format (“id” . string), 是如何 写 自定义参数的方式的?

针对所有语言,扩展 org-babel-execute-src-block 函数。针对特定语言,扩展 org-babel-execute-src-block:<LANG> 函数。

直接参考这些函数的实现就可以,如果觉得 org-babel-execute-src-block 太长太乱,这有个简单的例子,给 ob-php 增加了一个 :php </path/to/php-bin> 参数,只有 4 行代码:Add support for header arguments `:php' · twlz0ne/ob-php@b29034d · GitHub

  • :+1: :+1:

  • 很优雅的方法 (自定义参数的方式).

  • 具体到这个 issue, 似乎这种优雅的方法会绕弯路, 这里用不上.

    • 原因是, 本质还是要 重写 org-babel–string-to-number 方法.
    • format 只有 嵌入到 org-babel-execute-src-block 去解析 :var 才起到作用.
  • 谢谢 @twlz0ne

@yssource 函数已更新 :point_right: #7

1 个赞

我把这个函数 “pr” 给 org-mode 了,已被采纳:

I added TINYCHANGE at the end of the commit message and applied your patch on “next” branch (Org 9.3).

Thank you.

Regards,

Nicolas Goaziou

2 个赞

太好了.

有这个PR链接地址吗?

并非常规的 pr,而是通过邮件发送补丁:[O] [PATCH] ob-core.el: Fix org-babel--string-to-number