버퍼의 모든 정규 표현식 일치를 목록으로 가져옵니다.


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입니다. 생각조차하지 않았습니다 . 소스를 살펴 봐야합니다.
nanny

나는 내부를 들여다 보았고, 그 코드는 너무 많은 일을하고, 용도 변경이 쉽지 않다. 다음 후보는 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 "^.*$" ""). 유효한 정규 표현식, 유효한 문자열이지만 종료되지 않습니다.
Phil Lord

8

occur범용 인수로 호출 하면 *Occur*파일 이름, 행 번호 또는 헤더 정보가 아닌 일치하는 것으로 만 버퍼 를 채울 수 있습니다. 캡처 그룹과 결합하면 원하는 패턴을 추출 할 수 있습니다.

예를 들어, C-u M-x occur그 다음에 \"\(.*\)\"사용자에게 어떤 캡처 그룹을 수집 할 것인지 묻는 메시지가 표시되고 (default \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-stringmatch-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)))

이것이 괜찮다면 (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.