5

考虑这种情况:我有一些看起来像这样的数据:

1.9170000E+03 $ 1.6909110E+00
1.4550000E+03 $ 1.7775459E+00 1.1800000E + 03
$ 1.8771469E+00
1.0000000E+ 00 1.0000000E+03 2.5585915e+00

请注意,分隔两列的美元符号可以是任何字符(范围从一定数量的空格、\t(制表符)字符、逗号或几乎任何唯一用于分隔列的字符。另请注意数据可能有两列以上。

现在我想重新格式化数据块,以便某一列中的所有项目都列在一行中(由我在上面的示例中标记为 $ 的字符分隔):第 0 列中的项目填充第 0 行,第 1 列中的项目填充第 1 行,依此类推。

是否有预定义的 emacs 函数可以做到这一点?或者如果没有,是否有一些“自卷”功能来实现这一目标?

此外,我对执行相反操作的函数非常感兴趣,即取一些行并将它们放入列结构中。

任何帮助深表感谢!

4

2 回答 2

7

您可以使用csv-mode(可从package.el)。这是一个简单的转置操作。为此,请自定义 to 的值,csv-separators然后'("$")使用C-c C-t.

于 2013-04-18T16:49:06.943 回答
1

只是为了练习:

(defun transpose-table (begin end &optional numcols)
  (interactive "r\nP")
  (save-excursion
    (goto-char begin)
    (move-beginning-of-line 1)
    (let ((separators
           (if numcols
               (loop for i from 0 upto
                     (if (numberp numcols) numcols (car numcols))
                     for sep =
                     (read-string
                      (format "%d'th column separator (RET to terminate): " i))
                     until (string= sep "")
                     collect sep)
             (let ((x (list " "))) (nconc x x))))
          (end (save-excursion
                 (goto-char end)
                 (move-end-of-line 1)
                 (point))) lines)
      (loop while (< (point) end)
            for start = (point)
            for line = (buffer-substring 
                        start 
                        (progn (move-end-of-line 1) (point)))
            for numlines from 0
            with numrows = 0
            with longest-word = 0
            collect (loop for i from 0 below (length line)
                          with last-pos = 0
                          with rows = 0
                          with sep = separators
                          for sep-length = (length (car sep))
                          if (and (< (+ sep-length i) (length line))
                                  (string= (car sep)
                                           (substring line i (+ i sep-length))))
                          collect (substring line last-pos i) into words
                          and do (setf longest-word (max longest-word (- i last-pos))
                                       last-pos (+ i sep-length)
                                       sep (cdr sep) rows (1+ rows))
                          end
                          finally (return
                                   (progn
                                     (setf numrows (max rows numrows))
                                     (if (< last-pos (length line))
                                         (append words (list (substring line last-pos)))
                                       words))))
            into lines
            collect longest-word into word-lengths
            do (unless (eobp) (forward-char))
            finally 
            (loop initially (delete-region begin end)
                  for i from 0 to numrows do
                  (loop for line on lines 
                        for cell-length in word-lengths do
                        (if (caar line)
                            (let ((insertion (caar line)))
                              (insert insertion
                                      (make-string
                                       (- cell-length (length insertion) -1) ?\ ))
                              (rplaca line (cdar line)))
                          (insert (make-string (1+ cell-length) ?\ ))))
                  (insert "\n"))))))

也许使用 fromcsv-mode实际上会更好,但无论如何你都可以尝试这个:)

它是如何工作的:如果您将其称为M-xtranspose-table,那么它将假定表格列由单个空格分隔,但是,如果您使用数字参数调用它(例如,M-3M-xtranspose-table,那么它将提示您收集 3 个列分隔符。您也可以将其称为,并在被要求提供额外分隔符时C-uC-uM-xtranspose-table选择不提供所有 16 个分隔符。RET

我找不到正确的数字功能的序数打印......所以,对不起“1'th”和“2'th”英文:)

于 2013-04-19T21:32:32.813 回答