在Emacs Lisp中awk'{print $ 2,“,”,$ 1}'?

时间:2010-02-14 06:11:37

标签: awk elisp

有时我会使用AWK提取和/或反转数据文件中的列。

awk '{print $2,",",$1}' filename.txt

我如何使用Emacs Lisp做同样的事情?

(defun awk (filename col1 &optional col2 col3 col4 col5)
  "Given a filename and at least once column, print out the column(s)
values in the order in which the columns are specified."
...
)
;; Test awk
(awk "filename.txt" 1); Only column 1
(awk "filename.txt" 2 1); Column 2 followed by column 1
(awk "filename.txt" 3 2 1); Columns 3,2 then 1

示例filename.txt

a   b  c
1   2  5

示例输出:

b , a
2 , 1

3 个答案:

答案 0 :(得分:2)

你打算如何使用它?您是否计划将其用作命令行脚本?在这种情况下,您需要像hello world question一样打包它。

或者,您是否计划以交互方式使用它,在这种情况下,您可能希望将输出放在新缓冲区中...

此代码完成了基础知识。您需要更新它以符合您的使用模式。

(defun awk (filename &rest cols)
  "Given a filename and at least once column, print out the column(s) values
in the order in which the columns are specified."
  (let* ((buf (find-file-noselect filename)))
    (with-current-buffer buf
      (while (< (point) (point-max))
        (let ((things (split-string (buffer-substring (line-beginning-position) (line-end-position))))
              (c cols)
              comma)
          (while c
            (if comma
                (print ", "))
            (print (nth (1- (car c)) things))
            (setq comma t)
            (setq c (cdr c)))
          (print "\n")
          (forward-line))))
    (kill-buffer buf)))

答案 1 :(得分:0)

我采用了Trey的解决方案并生成了一个从Unix shell运行的脚本。它不需要命令行参数,因为我不确定如何将命令行-args-left 结果转换为适当的参数。


#!/usr/bin/emacs --script

;; ./awk.el; # Change the last line of this file to contain the desired values.
;;
(defun awk (filename &rest cols)
  "Given a filename and at least once column, print out the column(s) values
in the order in which the columns are specified."
  (let* ((buf (find-file-noselect filename)))
    (with-current-buffer buf
      (while (< (point) (point-max))
        (let ((things (split-string (buffer-substring (line-beginning-position) 
                          (line-end-position))))
              (c cols)
              comma)
          (while c
            (if comma
                (princ ", "))
            (princ (nth (1- (car c)) things))
            (setq comma t)
            (setq c (cdr c)))
            (princ "\n")
          (forward-line))))
    (kill-buffer buf)))

(awk "/tmp/foo.txt" 2 1)

答案 2 :(得分:0)

使用dash.els.el中的功能:

(defun print-columns (s &rest is)
  (s-join "\n"
          (--map (s-join ", "
                         (-select-by-indices is (cons it (s-split " " it t))))
                 (s-lines s))))

(print-columns "a  b c\n1  2 3" 3 2 1 0) ; output:
;; c, b, a, a  b c
;; 3, 2, 1, 1  2 3

默认情况下,awk将文本视为一系列记录(由换行符分隔),每个记录都是一系列字段(由空格分隔)。因此,在上面的示例中,c是记录a b c的字段。函数print-columns接收文本,按换行符s-lines分隔,从每条记录中选择某些字段,用逗号s-join连接它们,将结果与换行符连接起来。最重要的函数是dash的{​​{3}},它通过索引从列表中选择元素,并以与索引列表相同的顺序返回:

(-select-by-indices '(2 1 0) '(a b c d e)) ; => (c b a)