Bir satırdaki her satırı satır satır işlemek için deyimsel bir okuma yolu var mı?


11

Python'da bir dosyayı satır satır işlemek için aşağıdakileri yapardım:

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

Aynı şeyi elisp'te (dosyalar yerine arabelleklerle) nasıl yapacağınızı aramaya çalışırken, belirgin bir yol bulamadım.

(Sonunda istediğim iki sıralı veri yapısı, bir tanesi tüm satırlar bir normal ifade ile eşleşiyor, diğeri eşleşmeyenleri içeriyor.)

Yanıtlar:


23

Bunu yapmanın çeşitli yolları vardır. Kaushal'ın yolu şu şekilde daha verimli hale getirilebilir:

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

Ancak Emacs'da, dizgeler yerine tampon üzerinde çalışmak çok daha gelenekseldir. Bu nedenle, dizeyi ayıklamak ve daha sonra çalışmak yerine, şunları yaparsınız:

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

Ayrıca, tüm tampondan ziyade bir bölgede çalışmak istiyorsanız ve "işletmeniz" tamponu değiştirmeyi içeriyorsa, geriye doğru yapmak sıktır (böylece "sonunun" "bölgenizin konumu, arabelleği her değiştirdiğinizde hareket eder):

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

Bu optimizasyon ipuçları için teşekkürler! Sizden öğrenmek her zaman iyidir.
Kaushal Modi

Geçen pasajı Hakkında, bu şekilde olmalıdır: (let ((start (point))) (goto-char (point-max)) (while (> (point) start) ... (forward-line -1)))?
Kaushal Modi

Hayır, en son pasajı sadece varsayar startve endfaaliyet istediğiniz bölgeyi sınırlayan değişkenleri mevcut bulunmaktadır.
Stefan

6

Herhangi bir deyimsel yol bilmiyorum ama bununla geldim:

(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

Aşağıdaki olabildiğince deyimsel olduğunu düşünüyorum:

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

DÜZENLEME: İşte başka bir çözümdür loopyerine dolistve hangi zamanda bunlar normal ifade eşleşmesi olsun veya olmasın göre satırları sınıflandırır:

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

Bu işlevin çıktısına bir değişken ayarlarsanız, örneğin (setq x (loop ...)), eşleşen olmayan satırların listesi, eşleşmeyen satırların (car x)listesi ile bulunur (cdr x).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.