【问题标题】:Creating org-tables from the results of a code block从代码块的结果创建组织表
【发布时间】:2019-04-09 18:17:21
【问题描述】:

我正在尝试根据使用“;”的 CSV 文件的内容创建一个组织表作为分隔符。

我认为有一个源代码块来“cat”文件的内容然后将结果传递给创建表的函数会很容易,但我卡住了:我找不到方法使用第一个源代码块的“结果”。我知道的函数 (org-table-convert-region) 需要一个区域来工作,我不知道如何将“cat”-ed 文本作为区域传递。

#+NAME: csvraw
#+BEGIN_SRC sh :results raw
  cat afile.csv
#+END_SRC

感谢您帮助生成一个代码块,该代码块从我的 csv 文件中生成一个组织表,其中包含如下行:

ID;Region;SubRegion;Area;No
1234;Asia;India;45;2
24251;Europe;Romania;456;67

【问题讨论】:

    标签: emacs org-mode org-babel


    【解决方案1】:

    org-table-convert-region(绑定到C-c |)可以相当简单地进行转换。唯一的技巧是将; 指定为分隔符。您可以通过使用适当的前缀参数调用它来做到这一点 - 文档字符串说:

    (org-table-convert-region BEG0 END0 &optional SEPARATOR)
    
    Convert region to a table.
    
    The region goes from BEG0 to END0, but these borders will be moved
    slightly, to make sure a beginning of line in the first line is included.
    
    SEPARATOR specifies the field separator in the lines.  It can have the
    following values:
    
    (4)     Use the comma as a field separator
    (16)    Use a TAB as field separator
    (64)    Prompt for a regular expression as field separator
    integer  When a number, use that many spaces, or a TAB, as field separator
    regexp   When a regular expression, use it to match the separator
    nil      When nil, the command tries to be smart and figure out the
             separator in the following way:
             - when each line contains a TAB, assume TAB-separated material
             - when each line contains a comma, assume CSV material
             - else, assume one or more SPACE characters as separator.
    

    (64)的值就是连续三个C-u,所以过程如下:

    • 插入带有C-x i的CSV文件。
    • C-x C-x 将插入的内容标记为活动区域。
    • C-u C-u C-u C-c | ; RET

    更酷的是,在 CSV 文件的第一行和其余行之间留一个空行,将自动使第一行成为表格中的标题。

    您也可以将其封装在代码块中:

    #+begin_src elisp :var file="/tmp/foo.csv" :results raw
      (defun csv-to-table (file)
        (with-temp-buffer
          (erase-buffer)
          (insert-file file)
          (org-table-convert-region (point-min) (point-max) ";")
          (buffer-string)))
    
      (csv-to-table file)
    #+end_src
    
    #+RESULTS:
    | a | b | c |
    |---+---+---|
    | d | e | f |
    | g | h | i |
    

    【讨论】:

    • 非常感谢您提供信息丰富的回复。您提出的解决方案紧凑,但非常“易读”。
    【解决方案2】:
    (defun jea-convert-csv-to-org-table (fname)
      (interactive "fCSV to convert: ")
      (let ((result '("|-\n")))
        (with-temp-buffer
          (save-excursion (insert-file-contents-literally fname))
          (while (and (not (eobp)) (re-search-forward "^\\(.+\\)$" nil t nil))
            (push (concat "|" (replace-regexp-in-string ";" "|" (match-string 1)) "|\n")
                  result))
          (push '"|-\n" result))
        (concat (seq-mapcat #'identity (reverse result)))))
    

    在 ~/.emacs 文件中安装 elisp 代码并重新启动 emacs。或者,更好的是,eval 它存在(CTRL+x, CTRL+eALT+x eval-last-sexp)。

    #+NAME: csvraw
    #+BEGIN_SRC elisp :results raw
      (jea-convert-csv-to-org-table "/Users/jamesanderson/Downloads/test1.csv")
    #+END_SRC
    

    请注意上面从sh 更改为elisp。这是它的动图: emacs converting csv to org table

    代码没有针对大文件进行优化,坦率地说,代码很快就被组合在一起了。但是,经过一点点测试,似乎可以工作。

    【讨论】:

    • 你可以通过修改缓冲区文本并一次性提取它来提高效率,(defun nvp-convert-csv-to-org-table (fname) (interactive (list (read-file-name "CSV to convert: "))) (with-temp-buffer (save-excursion (insert-file-contents-literally fname)) (while (not (eobp)) (insert "|") (while (search-forward ";" (line-end-position) 'move) (replace-match "|")) (insert "|") (forward-line)) (buffer-string)))
    • James,非常感谢您的回复并花时间处理我的请求。我使用问题中提到的 csv 示例文件按照您的说明进行操作,但出现了问题:该函数创建了新的缓冲并在那里复制 csv 文件的内容,但挂起,迫使我多次使用 <kbd>Ctrl-g</kbd> 重新获得对 emacs 的控制。
    • @jenesaisquoi,感谢您提出改进建议。我会试试你的版本,完成后在这里发布。
    • @jenesaisquoi 正确:我使用 Edebug 来弄清楚发生了什么,事实上,while 循环永远持续下去:它不断将|\n 字符串连接到result
    • James,我修改了您提出的代码,为 while 循环添加了终止条件。我编辑了您的答案以反映更改:我想我必须等待修改经过同行评审才能看到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-08
    • 2018-06-22
    • 1970-01-01
    • 2014-05-15
    • 2017-12-11
    • 2011-03-21
    • 2011-01-13
    相关资源
    最近更新 更多