awk '{print $ 2, ",", $ 1}' в Emacs Lisp? - PullRequest
5 голосов
/ 14 февраля 2010

Иногда я использую 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 голосов
/ 14 февраля 2010

Как вы собираетесь использовать это? Планируете ли вы использовать его в качестве сценария командной строки? В этом случае вам нужно будет упаковать его следующим образом: 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)))
0 голосов
/ 16 февраля 2015

Используйте функции от dash.el и s.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)
0 голосов
/ 15 февраля 2010

Я взял решение Трея и создал скрипт, который запускается из оболочки Unix. Он не принимает параметры командной строки, потому что я не знал, как преобразовать результаты command-line-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 (&lt (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)

...