バッファの各行を読み取って行ごとに処理する慣用的な方法はありますか?


11

Pythonでは、次のようにして、ファイルを1行ずつ処理します。

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

elisp(ファイルの代わりにバッファを使用)で同じことを行う方法を調べようとしたところ、明確な方法が見つかりませんでした。

(私が最後にしたいのは、2つの順序付けられた行のデータ構造です。1つはすべての行が正規表現に一致し、もう1つは一致しなかった行を含みます。)

回答:


22

それを行うにはさまざまな方法があります。Kaushalの方法は、次のようにすると、かなり効率的になります。

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

しかしEmacsでは、文字列ではなくバッファで作業する方がはるかに慣習です。文字列を抽出してから作業するのではなく、次のようにします。

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

また、バッファ全体ではなくリージョンを操作する場合、「操作」にバッファの変更が含まれる場合は、逆方向に行うことがよくあります(「終了"バッファーを変更するたびにリージョンの位置が移動します):

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

これらの最適化のヒントをありがとう!あなたから学ぶことは常に良いです。
Kaushal Modi

最後のスニペットについては、次のようにすべき(let ((start (point))) (goto-char (point-max)) (while (> (point) start) ... (forward-line -1)))ですか?
Kaushal Modi 2016

いいえ、最後のスニペットは、操作対象の領域を区切る既存の変数であることstartを前提とendしています。
Stefan

6

私は慣用的な方法を知りませんが、これを思いつきました:

(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

以下は、それが得ることができるのと同じくらい慣用的であると思います:

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

編集:のloop代わりにを使用した別のソリューションを次に示しdolistます。これは、正規表現に一致するかどうかに応じて行を分類します。

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

たとえば、この関数の出力に変数を設定すると (setq x (loop ...))、一致する行のリストがに見つかり、一致しない行(car x)のリストはになり(cdr x)ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.