Każdy edytor tekstu, który może zastosować matematykę do tekstu zastępczego?

15

Mam duży plik XML

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

Muszę zwiększyć wszystkie wartości „param” o pewną liczbę. Mogę dopasować liczby, których potrzebuję przy wyszukiwaniu wyrażeń regularnych w wielu edytorach, ale jak zastosować matematykę do zamiany?

serg
źródło
1
Jaki system operacyjny Czy zamiast tego byłbyś zadowolony ze skryptu powłoki (co byłoby dość łatwe)? W każdym razie jestem tego pewien vimi emacsmogę to zrobić, ale może to wymagać napisania skryptu, a nie użycia pojedynczego polecenia.
frabjous
@frabjous pod Windows. Wolałbym nic nie pisać, jeśli to możliwe. Ale jeśli opublikujesz skrypt powłoki, jestem pewien, że będzie on przydatny dla wielu.
serg

Odpowiedzi:

18

Po nieco więcej pogrzebaniu, okazuje się, że vim może to zrobić za pomocą jednego polecenia, bez skryptów. Na przykład, aby dodać 50 do wszystkich następujących liczb, <obj param="możesz użyć:

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

Pozwól mi to zepsuć.

: jest ogólnym sposobem wprowadzania / oznaczania trybu wiersza poleceń w vimie.

%oznacza w ramach całego dokumentu; możesz podać zakres liczb, np. 1,50po prostu zrobić to w pierwszych 50 wierszach.

s jest skrótem do zastępstwa (jeśli chcesz, możesz napisać całe słowo)

@jest ogranicznikiem; możesz użyć dowolnej innej postaci, o ile nie ma jej w tym, czego szukasz. Po prostu użyj go trzy razy. (Składnia jest podobna do sed.)

Wszystko do następnego wystąpienia separatora @ to wzorzec reg ex, którego należy szukać, w tym przypadku <obj param="po nim \d\+, czyli dowolna liczba cyfr. \(I \)są tam ustawić całą sekwencję cyfr jako pojedynczy reg ex grupy, która będzie pasować jak odwołania wstecznego \1lub vim za submatchpolecenie.

Następnie separator @oznacza to, co następuje jako tekst zastępczy.

Na \=początku tutaj oznacza zastąpienie wyniku jakiegoś wyrażonego wyrażenia zamiast wzorca reg ex lub łańcucha, który jest tutaj kluczowy.

Następnie mamy '<obj param="'początek tekstu zastępczego. .Który następuje jest funkcja Vima na łączenie ciągów.

submatch(1)jest wbudowaną funkcją vima, której można używać tylko w poleceniu podstawienia, i zwraca ciąg znaków taki sam jak wyrażenie regularne \1; użyjesz submatch(2)jako odpowiednika wyrażeń regularnych \2i tak dalej. ( \0to cały dopasowany wzór, ale nie chcemy tego tutaj.) Wzorzec \(i \)w wyszukiwaniu są używane do zaznaczenia tego, co się liczy submatch(1).

Stąd (submatch(1) + 50)daje wynik dodania 50 do liczby, która następuje po cyfrach <obj param="w formularzu wzorca wyszukiwania.

Separator @jest ponownie używany do oznaczania końca tekstu zastępczego.

Flaga gsłuży do globalnego zastąpienia podstawień; możesz to pominąć, jeśli chcesz tylko zastąpić pierwszą instancję w każdej linii.

Prawdopodobnie możesz dowiedzieć się, jak dodawać różne liczby, odejmować, dzielić itp.

frabjous
źródło
To świetnie, miałem plik GPX, który był uszkodzony, ponieważ wartości długości geograficznej były całkowicie nieprawidłowe. Na szczęście szerokość geograficzna była w porządku, więc korzystając z mapy udało mi się ustalić, jaka powinna być pierwsza poprawna wartość, wykonać matematykę i ustalić, że muszę odjąć 4294.567548 od każdej wartości, aby uzyskać poprawną wartość. Jedyną przeszkodą, jaką miałem, było to, że ta metoda nie działała na liczbach zmiennoprzecinkowych, więc po prostu zrobiłem każdą stronę przecinka dziesiętnego jako oddzielne podstawienia, jeden -4294 i jeden -567548.
farsz
7

W Emacsie (od wersji 23): służy \,do wykonywania dowolnego kodu Lisp w zamianie wyrażeń regularnych . Na przykład, aby obliczyć liczby, których możesz użyć

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

W Vimie: zacznij zastępować tekst za pomocą \=(patrz :help sub-replace-special). Na przykład, aby obliczyć liczby:

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

Kilka edytorów pozwala robić takie rzeczy za pomocą makr: zdefiniuj makro, które 1. szuka następnego dopasowania i 2. wykonuje zamianę (w razie potrzeby za pomocą zewnętrznego narzędzia arytmetycznego); powtórz makro tyle razy, ile masz dopasowań.

Gilles „SO- przestań być zły”
źródło
Niedoceniana odpowiedź. Krótki i obejmuje 2 redaktorów + ogólne etui.
derekv
1

Możesz to zrobić za pomocą vima. Wystarczy otworzyć plik i zarejestrować makro . Przykład: Wyszukaj dowolny numer

/[0-9]{1,}

następnie naciśnij q i a (zapisz makro w rejestrze a). Następnie naciśnij Ctrl-X (zwiększając liczbę o 1), a następnie naciśnij n (dla następnego wyniku wyszukiwania). Po wykonaniu tej czynności naciśnij ponownie przycisk q, aby zapisać makro. Teraz możesz zastosować makro do następnego numeru, naciskając @ + a. Spowoduje to zmianę aktualnego numeru i przejście do następnego. Powtarzając to lub używając x @ a, możesz powtórzyć to x razy.

Cóż, ten opis może nie być wystarczający, aby pokazać, jak można to zrobić. Wystarczy zapoznać się z samouczkiem opisującym mechanizm makr w vimie.

evnu
źródło
Co jeśli muszę zmienić liczbę nie o 1, ale o milion? A może użyć mnożenia / dzielenia?
serg
1
To proste, jeśli chcesz dodać stałą x do każdej liczby: x + Ctrl + a. Czy musisz dodać różne liczby?
evnu