awk '{print $2,",",$1}' in Emacs Lisp?

5

我偶尔使用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个回答

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)))

我听说应该使用 with-current-buffer 而不是 save-excursionset-buffer - pheaver
你为什么要在每列后面打印换行符?你肯定是想在打印完一行中所有选定的列之后再打印它吧? - A. Levy

0

我采用了Trey的解决方案,并编写了一个可以从Unix shell运行的脚本。它不接受命令行参数,因为我不确定如何将command-line-args-left结果转换为正确的参数。


#!/usr/bin/emacs --script
;; ./awk.el; # 更改此文件的最后一行以包含所需的值。 ;; (defun awk (filename &rest cols) "给定文件名和至少一列,按指定的顺序打印出列(s)值。" (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)

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-select-by-indices,它通过索引从列表中选择元素,并按与索引列表相同的顺序返回它们:
(-select-by-indices '(2 1 0) '(a b c d e)) ; => (c b a)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接