Có một cách đọc thành ngữ từng dòng trong bộ đệm để xử lý từng dòng không?


11

Trong Python tôi sẽ làm như sau để xử lý một dòng tệp theo dòng:

with open(infile) as f:
    for line in f:
        process(line)

Cố gắng tìm kiếm cách làm tương tự trong elisp (với bộ đệm thay vì tập tin), tôi thấy không có cách rõ ràng.

(Điều tôi muốn kết thúc là hai cơ sở dữ liệu được sắp xếp theo thứ tự, một dòng có tất cả các dòng khớp với biểu thức chính quy, dòng còn lại chứa những dòng không khớp.)

Câu trả lời:


22

Có nhiều cách khác nhau để làm điều đó. Cách của Kaushal có thể được thực hiện tốt hơn một chút, với:

(goto-char (point-min))
(while (not (eobp))
  (let ((line (buffer-substring (point)
                                (progn (forward-line 1) (point)))))
    ...))

Nhưng trong Emacs, thông thường hơn là làm việc trên bộ đệm hơn là trên chuỗi. Vì vậy, thay vì trích xuất chuỗi và sau đó làm việc với nó, bạn chỉ cần làm:

(goto-char (point-min))
(while (not (eobp))
  ...
  (forward-line 1))

Ngoài ra, nếu bạn muốn hoạt động trên một khu vực chứ không phải trên toàn bộ bộ đệm và nếu "hoạt động" của bạn bao gồm sửa đổi bộ đệm, bạn thường phải làm điều đó ngược lại (để bạn không bị cắn bởi thực tế là "kết thúc "Vị trí khu vực của bạn di chuyển mỗi khi bạn sửa đổi bộ đệm):

(goto-char end)
(while (> (point) start)
  ...
  (forward-line -1))

Cảm ơn những lời khuyên tối ưu hóa! Luôn luôn tốt để học hỏi từ bạn.
Kaushal Modi

Về đoạn trích cuối, có nên theo cách này : (let ((start (point))) (goto-char (point-max)) (while (> (point) start) ... (forward-line -1)))?
Kaushal Modi

Không, đoạn mã cuối cùng chỉ giả định rằng startendlà các biến hiện có phân định vùng mà chúng tôi muốn hoạt động.
Stefan

6

Tôi không biết bất kỳ cách thành ngữ nào nhưng tôi đã nghĩ ra điều này:

(defun my/walk-line-by-line ()
  "Process each line in the buffer one by one."
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (not (eobp))
      (let* ((lb (line-beginning-position))
             (le (line-end-position))
             (ln (buffer-substring-no-properties lb le)))
        (message ">> %s" ln) ; Replace this with any processing function you like
        (forward-line 1)))))

1

Tôi nghĩ rằng sau đây là thành ngữ như nó có thể nhận được:

(dolist (line (split-string (buffer-string) "\n")) 
  ... process line here ...
  )

EDIT: Đây là một giải pháp khác loopthay thế dolistvà cũng phân loại các dòng theo liệu chúng có khớp với biểu thức chính quy của bạn hay không:

(loop for line in (split-string (buffer-string) "\n")
  if (string-match "your-regexp" line)
    collect line into matching
  else
    collect line into nonmatching
  finally return (cons matching nonmatching)
  )

Nếu bạn đặt một biến thành đầu ra của hàm này, giả sử (setq x (loop ...)), danh sách các dòng phù hợp mong muốn sẽ được tìm thấy (car x), với danh sách các dòng không khớp (cdr x).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.