2012-12-04 12 views
5

Dies zu Emacs: regular expression replacing to change caseEmacs: regulärer Ausdruck Fall ersetzen zu ändern (in Skripten)

Mein zusätzlichen Problem verbunden ist, ist, dass ich Skript muß die Such ersetzen, sondern die "\,()" Lösung funktioniert (für mich) nur dann, wenn verwendet interaktiv (emacs 24.2.1). In einem Skript gibt es den Fehler: "Ungültige Verwendung von \' im Ersetzungstext".

Ich schreibe normalerweise eine "perform-replace" in eine Datei, die bei Bedarf geladen wird. Etwas wie:

(führen Ersetzen "<\\([^>]+\\)>" "<\\,(downcase \1)>" tt nil 1 Null (Punkt-min) (Punkt-max))

Es sollte möglich sein, eine Funktion aufzurufen den Ersatz (pg 741 of the emacs lisp manual) zu erzeugen, aber ich habe versucht, viele Variationen der folgenden ohne Glück:

(defun myfun() 
    (downcase (match-string 0))) 

(perform-replace "..." (myfun .()) t t nil) 

Kann jemand helfen?

Antwort

3

Konstrukte wie \,() sind nur in interaktiven Aufrufen an query-replace erlaubt, weshalb sich Emacs in Ihrem Fall beschwert.

Die Dokumentation von perform-replace erwähnt, dass Sie es nicht in elisp Code verwenden sollte und schlägt eine bessere Alternative, auf dem wir den folgenden Code bauen:

(while (re-search-forward "<\\([^>]+\\)>" nil t) 
    (replace-match (downcase (match-string 0)) t nil)) 

Wenn Sie noch interaktiv Abfrage zu wollen der Benutzer über die Ersetzungen, mit perform-replace wie Sie, ist wahrscheinlich das Richtige zu tun. Es gab ein paar anderen Probleme in Ihrem Code:

  1. Wie in den elisp manual angegeben ist, muss die Ersatzfunktion zwei Argumente (die Daten, die Sie in der cons Zelle liefern und die Anzahl des Ersatzes bereits gemacht).

  2. Wie in der Dokumentation von query-replace-regexp angegeben (oder den elisp manual), müssen Sie sicherstellen, dass case-fold-search oder case-replace auf Null gesetzt, so dass der Fall Muster auf den Ersatz nicht übertragen werden.

  3. Sie müssen die Cons Zelle (myfun . nil) angeben, sonst wird es als Funktionsaufruf interpretiert und zu früh ausgewertet.

Hier ist eine Arbeitsversion:

(let ((case-fold-search nil)) 
    (perform-replace "<\\([^>]+\\)>" 
        `(,(lambda (data count) 
         (downcase (match-string 0)))) 
        t t nil)) 
+0

nop, ich brauche die Abfrage (! Y/n/etc.) und markieren Fähigkeiten ausführen Ersetzen (ein ich lieber nicht neu zu implementieren es mit y-oder-np + highlight-regexp o.ä.) –

+0

Vielleicht möchten Sie Ihre Frage so bearbeiten, dass sie diese Einschränkung widerspiegelt. Wie auch immer, ich schlug eine Lösung vor, die auf "perform-replace" basiert und Ihre Anforderungen erfüllen sollte. – Francesco

2

C-h f perform-replace sagt:

Don't use this in your own program unless you want to query and set the mark 
just as `query-replace' does. Instead, write a simple loop like this: 

    (while (re-search-forward "foo[ \t]+bar" nil t) 
    (replace-match "foobar")) 

Jetzt sind die "<\\,(downcase \1)>" Bedürfnisse durch einen Elisp Ausdruck ersetzt werden, die die richtige Zeichenfolge, wie (format "<%s>" (downcase (match-string 1))) baut .

Wenn Sie die Abfrage und Zeug benötigen, dann möchten Sie vielleicht versuchen: C-M-% f\(o\)o RET bar \,(downcase \1) baz RET und dann C-x RET RET, um zu sehen, welche Argumente während des interaktiven Aufrufs konstruiert wurden.

werden Sie sehen, entdecken (noch besser, wenn Sie auf replace.el in C-h f perform-replace klicken Sie auf den Quellcode der Funktion zu sehen), dass das replacements Argument die Form annehmen kann (FUNCTION. Argument). Genauer gesagt, enthält der Code einen Kommentar, einige Details geben:

;; REPLACEMENTS is either a string, a list of strings, or a cons cell 
;; containing a function and its first argument. The function is 
;; called to generate each replacement like this: 
;; (funcall (car replacements) (cdr replacements) replace-count) 
;; It must return a string. 
+0

Ich muss "abfragen" :-) –