มีวิธีการอ่านแต่ละบรรทัดในบัฟเฟอร์เพื่อประมวลผลทีละบรรทัดหรือไม่?


11

ใน Python ฉันจะทำสิ่งต่อไปนี้เพื่อประมวลผลไฟล์ทีละบรรทัด:

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

พยายามค้นหาวิธีการทำเช่นเดียวกันใน elisp (ด้วยบัฟเฟอร์แทนไฟล์) ฉันไม่พบวิธีที่ชัดเจน

(สิ่งที่ฉันต้องการที่จะจบลงด้วยคือสองสายข้อมูลโครงสร้างข้อมูลที่สั่งซื้ออย่างใดอย่างหนึ่งที่มีทุกบรรทัดที่ตรงกับ regex อื่น ๆ ที่มีผู้ที่ไม่ตรงกับ.)

คำตอบ:


23

มีหลายวิธีที่จะทำ วิธีของ 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

ไม่ข้อมูลโค้ดสุดท้ายนั้นจะถือว่า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.