Jeder Texteditor, der etwas Mathe auf Ersetzungstext anwenden kann?

14

Ich habe eine große XML-Datei

<obj param="2542">
<obj param="2333">
<obj param="6433">

Ich muss alle "param" -Werte um eine bestimmte Anzahl erhöhen. Ich kann mit der regexp-Suche in vielen Editoren Zahlen abgleichen, die ich brauche.

serg
quelle
1
Welches Betriebssystem? Würdest du stattdessen mit einem Shell-Skript zufrieden sein (was ziemlich einfach wäre)? Ich bin mir jedenfalls sicher vim und emacs kann dies tun, aber es muss möglicherweise ein Skript geschrieben werden, anstatt einen einzelnen Befehl zu verwenden.
frabjous
@frabjous unter Windows. Ich möchte lieber nichts schreiben, wenn möglich. Wenn Sie jedoch ein Shell-Skript veröffentlichen, kann es sicherlich für viele nützlich sein.
serg

Antworten:

18

Nach etwas mehr Stöbern stellt sich heraus, dass vim dies mit einem einzigen Befehl ohne Scripting tun kann. B. 50 zu allen folgenden Zahlen hinzufügen <obj param=" Du könntest benutzen:

:%s@<obj param="\(\d\+\)@\='<obj param="' . (submatch(1) + 50)@g

Lass mich das brechen.

: ist der allgemeine Weg, um den Befehlszeilenmodus in vim einzugeben.

% bedeutet im Rahmen des gesamten Dokuments; Sie könnten einen Zahlenbereich eingeben, z. 1,50 tun Sie es einfach innerhalb der ersten 50 Zeilen.

s ist die Abkürzung für Ersatz (Sie können das ganze Wort ausschreiben, wenn Sie möchten)

@ ist das Trennzeichen; Du könntest jeden anderen Charakter verwenden, solange es nicht in dem ist, wonach du suchst. Verwenden Sie es einfach dreimal. (Die Syntax ist ähnlich zu sed.)

Alles bis zum nächsten Vorkommen des Trennzeichens @ ist in diesem Fall das zu suchende reg ex-Muster <obj param=" gefolgt von \d\+, das ist eine beliebige Anzahl von Ziffern. Das \( und \) gibt es, um diese gesamte Ziffernfolge als eine einzige Reg-Ex-Gruppe festzulegen, die mit Rückreferenzen wie z \1oder vim submatch Befehl.

Dann das Trennzeichen @ kennzeichnet das, was als Ersatztext folgt.

Das \= Am Anfang bedeutet hier das Ersetzen des Ergebnisses eines ausgewerteten Ausdrucks anstelle eines Regex-Musters oder einer Zeichenfolge, die hier der Schlüssel ist.

Dann haben wir '<obj param="' für den Beginn des Ersetzungstextes. Das . Folgendes ist die Funktion von vim zum Verketten von Strings.

submatch(1) ist eine vim-eingebaute Funktion, die nur innerhalb eines Ersetzungsbefehls verwendet werden kann und den String zurückgibt, der dem regulären Ausdruck entspricht \1; du würdest verwenden submatch(2) für das Äquivalent von Regex \2 und so weiter. ( \0 ist das ganze passende Muster, aber das wollen wir hier nicht \( und \) Im Suchmuster wird angegeben, was als zählt submatch(1).

Daher (submatch(1) + 50) ergibt das Ergebnis der Addition von 50 zu der Zahl, auf die sich die Ziffern beziehen <obj param=" im Suchmusterformular.

Das Trennzeichen @ wird wieder verwendet, um das Ende des Ersetzungstextes zu markieren.

Die Flagge g wird verwendet, um die Substitutionen global zu machen; Sie könnten dies auslassen, wenn Sie nur die erste Instanz in jeder Zeile ersetzen möchten.

Von dort aus können Sie wahrscheinlich herausfinden, wie Sie verschiedene Zahlen hinzufügen, subtrahieren oder dividieren usw.

frabjous
quelle
Das ist großartig, ich hatte eine GPX-Datei, die beschädigt war, weil die Längengrade absolut ungültig waren. Glücklicherweise war die Breite in Ordnung, also konnte ich mithilfe einer Karte herausfinden, wie der erste korrekte Wert sein sollte, ein paar Berechnungen durchführen und herausfinden, dass ich 4294.567548 von jedem Wert abziehen musste, um den richtigen Wert zu erhalten. Der einzige Stolperstein, den ich hatte, war, dass diese Methode bei einer Fließkommazahl nicht funktionierte. Deshalb habe ich jede Seite des Dezimalzeichens als separate Ersetzungen verwendet, eine -4294 und eine -567548.
stuffe
7

In Emacs (seit Version 23): use \, beliebigen Lisp-Code in ausführen Regex-Ersetzung . Zum Beispiel, um die Zahlen zu quadrieren, die Sie verwenden könnten

M-x replace-regexp
param="\([0-9]+\)"
param="\,(* \#1 \#1)"

In Vim: Beginnen Sie Ihren Ersatztext mit \= (sehen :help sub-replace-special ). Zum Beispiel, um die Zahlen zu quadrieren:

s!param="\([0-9]\+\)"!\='param="'.submatch(1)*submatch(1).'"'!

Mit mehreren Editoren können Sie diese Art von Aufgaben mit Makros ausführen: Definieren Sie ein Makro, das 1. nach dem nächsten Treffer sucht und 2. die Ersetzung ausführt (ggf. mithilfe eines externen Tools für die Arithmetik); Wiederholen Sie das Makro so oft wie Sie Übereinstimmungen haben.

Gilles
quelle
Unterschätzte Antwort Kurz und Sie behandeln 2 Redakteure + allgemeinen Fall.
derekv
1

Sie können vim verwenden, um das für Sie zu tun. Öffnen Sie einfach Ihre Datei und notieren Sie eine Makro . Beispiel: Suche nach einer beliebigen Nummer

/[0-9]{1,}

Drücken Sie dann q und a (Makro in Register a speichern). Danach drücken Sie Strg-X (Erhöhung der Zahl um 1) und anschließend n (für das nächste Suchergebnis). Nachdem Sie das getan haben, drücken Sie erneut q, um das Makro zu speichern. Jetzt können Sie das Makro auf die nächste Nummer anwenden, indem Sie @ + a drücken. Dies ändert die aktuelle Nummer und springt zur nächsten. Durch Wiederholen oder Verwenden von x @ a können Sie das x-mal wiederholen.

Nun, diese Beschreibung reicht möglicherweise nicht aus, um zu zeigen, wie dies möglich ist. Verweisen Sie einfach auf ein Tutorial, das den Makromechanismus in vim beschreibt.

evnu
quelle
Was ist, wenn ich die Zahl nicht um 1, sondern um eine Million ändern muss? Oder vielleicht eine Multiplikation / Division?
serg
1
Es ist einfach, wenn Sie jeder Zahl ein konstantes x hinzufügen möchten: x + Strg + a. Müssen Sie verschiedene Nummern hinzufügen?
evnu