รับการแข่งขัน regexp ทั้งหมดในบัฟเฟอร์เป็นรายการ


18

ในเว็บไซต์ Code Golf Stack Exchange วันนี้ฉันพบคำตอบนี้ใน Clojure กับคำถาม "รับลิงก์ทั้งหมดบนเว็บเพจ"

(->> (slurp "http://www.stroustrup.com")
     (re-seq #"(?:http://)?www(?:[./#\+-]\w*)+"))

หากไม่มีมาโครสุดหรูมันก็แค่นี้:

(re-seq #"(?:http://)?www(?:[./#\+-]\w*)+" (slurp "http://www.stroustrup.com"))

ส่งคืนรายการ:

("http://www.morganstanley.com/" "http://www.cs.columbia.edu/" "http://www.cse.tamu.edu" ...)

ฉันสามารถทำสิ่งที่คล้ายกันใน Emacs Lisp ได้หรือไม่

บางทีฟังก์ชั่นเช่น(re-seq regexp (buffer-string))นั้นกลับมาแล้ว'(firstmatch secondmatch thirdmatch ...)?


นี่คือสิ่งที่M-x occurทำ แต่ฉันจะมองหาฟังก์ชั่นระดับต่ำมากขึ้นในการทำเช่นนั้น
wvxvw

@wvxvw occurนั่นเป็นจุดที่ดีผมไม่ได้คิดเกี่ยวกับ ฉันจะต้องมองผ่านแหล่งที่มา
พี่เลี้ยงเด็ก

ฉันมองเข้าไปข้างในและโอ้ความฉิบหายรหัสนั้นมากเกินไปและมันไม่ง่ายเลยที่จะเปลี่ยนรหัสใหม่ไม่ใช่เลย ผู้สมัครคนต่อไปของฉันจะเป็นs.elแต่อาจจะมีมากกว่านั้น ที่นี่: github.com/magnars/s.el#s-match-strings-all-regex-stringวิธีการเกี่ยวกับเรื่องนี้?
wvxvw

คำตอบ:


16

นี่คือวิธีที่คุณสามารถทำได้โดยขึ้นอยู่กับสตริงตามที่ร้องขอ

(defun re-seq (regexp string)
  "Get a list of all regexp matches in a string"
  (save-match-data
    (let ((pos 0)
          matches)
      (while (string-match regexp string pos)
        (push (match-string 0 string) matches)
        (setq pos (match-end 0)))
      matches)))

; Sample URL
(setq urlreg "\\(?:http://\\)?www\\(?:[./#\+-]\\w*\\)+")
; Sample invocation
(re-seq urlreg (buffer-string))

ดูเหมือนจะยังไม่เสร็จสมบูรณ์คุณสามารถขยายคำตอบให้เป็นคำตอบที่ใช้งานได้จริงหรือไม่?
wasamasa

1
รหัสเสร็จสมบูรณ์ แต่ฉันยังเพิ่มตัวอย่างการใช้งาน คุณต้องการเห็นอะไรอีก
Alan Shutko

1
วิธีนี้ง่ายเกินไปน่าเสียดาย ลอง(re-seq "^.*$" "")ดู regexp ที่ถูกต้องสตริงที่ถูกต้อง แต่มันไม่เคยยุติ
Phil Lord

8

อาจเป็นที่น่าสังเกตว่าการเรียกใช้occurอาร์กิวเมนต์สากลทำให้*Occur*บัฟเฟอร์มีการจับคู่เท่านั้น - ไม่มีชื่อไฟล์หมายเลขบรรทัดหรือข้อมูลส่วนหัว เมื่อรวมกับกลุ่มการจับภาพสิ่งนี้จะช่วยให้กลุ่มหนึ่งสามารถแยกรูปแบบใดก็ได้ที่ต้องการ

ตัวอย่างเช่นC-u M-x occurตามด้วย\"\(.*\)\"จะแจ้งให้ผู้ใช้กลุ่มการรวบรวมที่จะรวบรวม (ค่าเริ่มต้น\1) แล้ววางเนื้อหาของทุกสตริงที่ยกมาลงใน*Occur*บัฟเฟอร์


5

ฉันมี emacs lisp ตอบคำถามที่โพสต์: /codegolf//a/44319/18848

การใช้โครงสร้างเดียวกัน (ในขณะที่ (ค้นหา) (พิมพ์)) คุณสามารถแก้ไขมันลงในฟังก์ชั่นเพื่อส่งข้อมูลที่ตรงกันในบัฟเฟอร์ไปยังรายการและส่งกลับดังนี้:

(defun matches-in-buffer (regexp &optional buffer)
  "return a list of matches of REGEXP in BUFFER or the current buffer if not given."
  (let ((matches))
    (save-match-data
      (save-excursion
        (with-current-buffer (or buffer (current-buffer))
          (save-restriction
            (widen)
            (goto-char 1)
            (while (search-forward-regexp regexp nil t 1)
              (push (match-string 0) matches)))))
      matches)))

คำตอบที่ดีโปรดทราบว่าคุณอาจต้องการแทนที่match-stringด้วยmatch-string-no-propertiesดังนั้นการเน้นไวยากรณ์จะไม่ถูกแยกออก คุณอาจต้องการผ่านการregexp-group-indexใช้งานเพื่อให้คุณสามารถเลือกข้อความที่เก็บไว้ เช่นเดียวกับการย้อนกลับลำดับการค้นหา (รายการปัจจุบันเป็นรายการสุดท้ายไปก่อน) ดูคำตอบนี้ซึ่งรวมถึงรุ่นที่แก้ไขแล้วemacs.stackexchange.com/a/38752/2418
ideasman42

3

การใช้s.elสิ่งนี้จะสั้นลง แต่น่าเสียดายที่มันให้การแข่งขันมากเกินไป:

(defun all-urls-in-buffer ()
  (s-match-strings-all
   "\\(?:http://\\)?www\\(?:[./#+-]\\w*\\)+"
   (buffer-string)))

หากนี่เป็นสิ่งที่ดี (regex สำหรับ URL นั้นยังไม่สมบูรณ์แบบ) นี่อาจจะสั้นลงและถ้าไม่เช่นนั้นฉันก็ไม่คิดว่าจะทำให้เตี้ยกว่าคำตอบของ Alan Shutko


2

ให้ฉันพูดถึงว่าทำไมฉันถึงคิดว่าสิ่งนี้ไม่ได้นำมาใช้ในแกนกลาง เพื่อเหตุผลด้านประสิทธิภาพ: ไม่จำเป็นต้องคัดลอกสร้างรายการส่งต่อและรวบรวมขยะ ให้เก็บสตริงทั้งหมดไว้เป็นบัฟเฟอร์แทนและดำเนินการด้วยขอบเขตการจับคู่จำนวนเต็ม นั่นเป็นวิธี occurการทำงานเช่น: *occur*มันตรงกับหนึ่งสายในเวลาและแทรกเข้าไปในการแข่งขัน มันไม่ตรงกับสตริงทั้งหมดในครั้งเดียวทำให้พวกเขาเข้าไปในรายการวนรอบในรายการที่จะแทรก *occur*และขยะเก็บรวบรวมรายการและสตริง

เช่นเดียวกับที่คุณไม่ได้เขียน(do (def x 1) (def x (+ 2 x)))ใน Clojure โดยค่าเริ่มต้นคุณไม่ควรลองให้ Elisp ทำงานเหมือนภาษาที่ใช้งานได้ ฉันจะรักถ้ามันเป็น แต่เราต้องทำเพราะสิ่งที่เรามีในขณะนี้


1

หากฉันอาจได้รับอนุญาตให้ใช้ปลั๊กลองดูที่ห้องสมุด "m-buffer" ของฉัน

(m-buffer-match buffer "foo")

fooกลับรายการของเครื่องหมายการแข่งขันไป

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.