2011-06-18 15 views
6

Na przykład chcę zrobić cały tekst w nawiasach,(), UPCASE. To trywialne wykonać następujące czynności interaktywnie:Emacs: w jaki sposób mogę zastąpić wyrażenie regexp za pomocą funkcji selekcji w defun?

M-x query-replace-regexp 
replace: "(\(.+?\))" 
with : "(\,(upcase \1))" 

Zamiast Chcę napisać defun który zrobi to:

(defun upcs() 
    (interactive) 
    (goto-char 1) 
    (while (search-forward "(\\(.+?\\))" nil t) (replace-match "(\\,(upcase \\1))" t nil))) 

ale to nie działa! Natomiast następujące prace (dołącza foo i bar do tekstów nawiasach):

(defun HOOK() 
    (interactive) 
    (goto-char 1) 
    (while (search-forward-regexp "(\\(.+?\\))" nil t) (replace-match "(foo \\1 bar)" t nil))) 

Odpowiedz

2

Rozwiązuje to problem.

(defun put-in-par (str) 
    (concat "(" str ")")) 

(defun upcs-luke() 
    (interactive) 
    (goto-char 1) 
     (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
      (replace-match (put-in-par (upcase (match-string 1))) t nil))) 

Podziękowania dla Billa i Łukasza Girvina za pomoc.

+0

Jeśli chcesz wyeliminować "put-in-par", możesz zrobić: (defun upcs-luke() (interaktywny) (goto-char 1) (podczas (search-forward-regexp "(\\ ([^ \\)] + \\)) "nil t) (zamień-zapakuj (concat" ("(upcase (string-match 1))") ") t nil))) – zev

+0

Również używając' format' dla ten cel byłby ładniejszy i bardziej elastyczny w bardziej skomplikowanych przypadkach. – ocodo

5

Przede wszystkim używasz search-forward w pierwszej funkcji. To przyjmuje raczej tekst literowy niż wyrażenie regularne. Powinieneś używać search-forward-regexp, tak jak w drugiej funkcji.

Po drugie, podczas gdy ten kod jest ważny jako wartość zastąpienia dla query-replace-regexp, nie sądzę, można przekazać je do replace-match:

(\\,(upcase \\1))

można uzyskać wartość meczu znaleziony przez search-forward-regexp przy użyciu funkcji match-string.

W końcu nie jestem pewien, czy twoje wyrażenie regularne wyszukiwania jest poprawne.

myślę, że trzeba coś wzdłuż tych linii:

(defun upcs() 
    (interactive) 
    (goto-char 1) 
     (while (search-forward-regexp "(\\([^\\)]+\\))" nil t) 
      (replace-match (upcase (match-string 1)) t nil))) 
+0

Dziękuję Luke. To faktycznie pozostawia dopasowane stringi nieuzbrojone. Ale znając poprawne wyrażenie dla dopasowania łańcuchowego - łatwo jest napisać defun, który wstawi go w nawiasy klamrowe. Opublikuję to jako "odpowiedź na twoje pytanie". Dzięki jeszcze raz. – Adobe

+0

@Adobe - nie ma za co. –

6

odpowiedź Luke'a prawie spełnia swoje zadanie, ale nie całkiem. Oryginalny plakat chciał, aby cały tekst zawarty w nawiasach był konwertowany na wielkie litery, podczas gdy kod Luke'a zamienia kod na wielkie litery, A TAKŻE usuwa nawias. Nieznaczna modyfikacja regex zapewnia prawidłowe rozwiązanie:

(defun upcs() 
(interactive) 
(goto-char 1) 
    (while (search-forward-regexp "\\([^\\)]+\\)" nil t) 
     (replace-match (upcase (match-string 1)) t nil))) 
+0

Dzięki Bill. Masz rację - odpowiedź Luke'a pozostawia niezobowiązującą strunę. Twoja odpowiedź powoduje jednak, że cały tekst wielkiej litery bufora.Napisałem prosty defun - i zawiera on odpowiedź Luke'a. Postawię ostateczne rozwiązanie jako "odpowiedź na twoje pytanie". Dzięki jeszcze raz. – Adobe

+0

Tak, mój kod usuwa nawiasy. Nie będę zawracać sobie głowy redagowaniem odpowiedzi, ponieważ OP opublikował poprawne rozwiązanie. –

0

To było bardzo przydatne, dziękuję wszystkim.

W trosce o oddanie więcej przykładów w internecie, poszedłem z tego:

(replace-regexp "\([\%\)\”\"]\..?\)[0-9]+" "\1") 

(który nie działa, ale który użył wyrażeń regularnych, które wyszło w trybie interaktywnym)

do tego:

(while (re-search-forward "\\([\\%\\\"\\”]\\)\\.?[0-9]+" nil t) 
    (replace-match (match-string 1) t nil)) 

potrzebowałem trzech backslashy przed wewnętrznym cudzysłowem.

Powiązane problemy