2013-12-09 43 views
0

我試圖讓從comint-mode派生的劣勢模式自動「鏈接」輸出中file:line:col的兩個變體。使用(?:x)|(?:y)重新搜索後退不起作用?

這樣做,我有一個正則表達式在非捕獲組中有兩個子模式,加入了|。每個子模式正好有三個捕捉組:

(concat 
    "\\(?:" ;; pattern 1 e.g. "; /path/to/file:1:1" 
    "; \\([^:]+\\):\\([0-9]+\\):\\([0-9]+\\)" 
    "\\)" 
    "\\|" 
    "\\(?:" ;; pattern 2 e.g. "location: #(<path:/path/to/file> 0 1" 
    "location: (#<path:\\([^>]+\\)> \\([0-9]+\\) \\([0-9]+\\)" 
    "\\)") 

的比賽事匹配第一子模式。但它從來沒有匹配的東西匹配子模式。

但是,第一個模式的存在似乎意味着第二個(?: ...)模式將永遠不匹配。如果我註釋掉第一種模式,那麼第二種模式纔會匹配。

如果我刪除了第一個子模式,讓

"\\(?:" ;; pattern 2 
    "location: (#<path:\\([^>]+\\)> \\([0-9]+\\) \\([0-9]+\\)" 
    "\\)" 

它的比賽,所以我知道,第二子模式是正確的。

或者,如果我保持第一個子模式,但將其更改爲類似「XXX」,沒有捕獲:

"\\(?:" ;; pattern 1 
    "XXXX" 
    "\\)" 
    "\\|" 
    "\\(?:" ;; pattern 2 
    "location: (#<path:\\([^>]+\\)> \\([0-9]+\\) \\([0-9]+\\)" 
    "\\)" 

它也適用。第一個子模式與不包含「XXXX」的示例輸入不匹配,第二個子模式接下來嘗試並匹配。

我很難過。我是否誤解了一般的正則表達式,或者這對Emacs來說是獨一無二的?


更多的上下文的情況下,它的問題:

(define-derived-mode inferior-foo-mode comint-mode "Inferior Foo" 
    ... 
    (add-hook 'comint-output-filter-functions 'linkify) 
    ...) 

(defun linkify (str) 
    (save-excursion 
    (end-of-buffer) 
    (re-search-backward (concat 
         "\\(?:" ;; pattern 1 
          "; \\([^:]+\\):\\([0-9]+\\):\\([0-9]+\\)" 
         "\\)" 
         "\\|" 
         "\\(?:" ;; pattern 2 
          "location: (#<path:\\([^>]+\\)> \\([0-9]+\\) \\([0-9]+\\)" 
         "\\)") 
         (- (buffer-size) (length str)) 
         t) 
    (when (and (match-beginning 0) 
       (match-beginning 1) (match-beginning 2) (match-beginning 3)) 
     (make-text-button 
     (match-beginning 1) (match-end 3) 
     'file (buffer-substring-no-properties (match-beginning 1) (match-end 1)) 
     'line (buffer-substring-no-properties (match-beginning 2) (match-end 2)) 
     'col (buffer-substring-no-properties (match-beginning 3) (match-end 3)) 
     'action #'go-to-file-line-col 
     'follow-link t)))) 
+1

你可能會發現[再生成器(http://www.emacswiki.org/emacs/ReBuilder)和[RX](http://www.emacswiki.org/emacs/rx)有用 –

+0

當然。在這種情況下,我的正則表達式本身實際上是正確的,但在我的代碼中,使用結果讓我對捕獲組的編號感到愚蠢。 –

回答

2

你被錯誤計數。該捕獲組第二的非捕獲組是(match-string 4)(match-string 5)(match-string 6)

還要注意,

(buffer-substring-no-properties (match-beginning 1) (match-end 1)) 

相當於短清晰版

(match-string-no-properties 1) 

我建議是這樣的:

(let ((m1 (or (match-string-no-properties 1) (match-string-no-properties 4))) 
     (m2 (or (match-string-no-properties 2) (match-string-no-properties 5))) 
     (m2 (or (match-string-no-properties 3) (match-string-no-properties 6)))) 
    (when (and m1 m2 m3) ... 
+0

哎呀。不知何故,我意識到'|'會導致第二個子模式從1重新編號。但顯然這是沒有意義的。還要感謝你的提示重新匹配字符串沒有屬性。順便說一句,您在編輯中添加的代碼幾乎就是我在嘗試原始答案時所寫的代碼。所以,呃。虛擬藥丸似乎現在正在消失。 :) –

2

您的正則表達式不符合其評論。

評論有#(;正則表達式有(#。該評論在location:之後有兩個空格;正則表達式有3個空格。如果你讓他們相應,那麼它似乎工作正常。例如:

(concat 
"\\(?:" ;; pattern 1 
"; \\([^:]+\\):\\([0-9]+\\):\\([0-9]+\\)" 
"\\)" 
"\\|" 
"\\(?:" ;; pattern 2 
"location: #(<path:\\([^>]+\\)> \\([0-9]+\\) \\([0-9]+\\)" 
"\\)") 
+0

好,但不幸的是,這是我在最後一秒添加示例的錯誤。抱歉誤導你,並感謝你的答覆,我會upvote。 –