Adakah editor teks yang bisa menerapkan beberapa matematika ke teks pengganti?

15

Saya punya file XML besar

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

Saya perlu meningkatkan semua nilai "param" dengan beberapa angka. Saya dapat mencocokkan angka yang saya butuhkan dengan pencarian regexp di banyak editor, tetapi bagaimana cara menerapkan beberapa matematika pada pengganti?

serg
sumber
1
Sistem operasi apa? Apakah Anda akan senang dengan skrip shell sebagai gantinya (yang akan cukup mudah)? Ngomong-ngomong, saya yakin vimdan emacsbisa melakukan hal semacam ini, tetapi mungkin perlu menulis skrip daripada menggunakan satu perintah.
frabjous
@frabjous di bawah windows. Saya lebih suka tidak menulis apa pun jika memungkinkan. Tetapi jika Anda memposting skrip shell saya yakin itu akan bermanfaat bagi banyak orang.
serg

Jawaban:

18

Setelah sedikit lebih bolak-balik, ternyata vim bisa melakukannya dengan satu perintah, tanpa scripting. Misalnya, untuk menambahkan 50 ke semua angka berikut <obj param="Anda dapat menggunakan:

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

Biarkan saya memecahnya.

: adalah cara umum untuk masuk / menandakan mode baris perintah di vim.

%berarti dalam lingkup seluruh dokumen; Anda bisa memasukkan rentang angka, misalnya, 1,50hanya melakukannya dalam 50 baris pertama saja.

s adalah singkatan untuk pengganti (Anda dapat menulis seluruh kata jika Anda suka)

@adalah pembatas; Anda dapat menggunakan karakter lain selama tidak dalam apa yang Anda cari. Cukup gunakan tiga kali. (Sintaksnya mirip dengan sed.)

Semuanya hingga kemunculan pembatas @ berikutnya adalah pola reg ex untuk dicari, dalam hal ini <obj param="diikuti oleh \d\+, yang merupakan angka berapa pun. The \(dan \)ada di sana untuk mengatur seluruh urutan digit ini sebagai grup reg ex tunggal yang akan cocok dengan referensi seperti \1, atau submatchperintah vim .

Kemudian pembatas @menandai bahwa apa yang mengikuti sebagai teks pengganti.

Di \=bagian awal di sini berarti menggantikan hasil dari beberapa ekspresi yang dievaluasi, bukan pola atau string reg ex, yang merupakan kunci di sini.

Kemudian kita miliki '<obj param="'untuk memulai teks pengganti. The .yang mengikuti adalah fungsi vim untuk concatenating string.

submatch(1)adalah fungsi built-in vim yang hanya dapat digunakan dalam perintah substitusi, dan mengembalikan string yang sama dengan regex \1; Anda akan menggunakan submatch(2)setara dengan regex \2dan sebagainya. ( \0adalah seluruh pola yang cocok, tetapi kami tidak ingin itu ada di sini.) \(Dan \)dalam pola pencarian digunakan untuk menandai apa yang dianggap sebagai submatch(1).

Oleh karena itu (submatch(1) + 50)berikan hasil menambahkan 50 ke angka yang diikuti digit <obj param="dalam bentuk pola pencarian.

Pembatas @lagi digunakan untuk menandai akhir teks pengganti.

Bendera gdigunakan untuk membuat pergantian global; Anda bisa menghilangkan ini jika Anda hanya ingin mengganti instance pertama pada setiap baris.

Anda mungkin dapat bekerja dari sana cara menambahkan angka yang berbeda, atau mengurangi, atau membagi, dll.

luar biasa
sumber
Ini hebat, saya punya file GPX yang rusak karena nilai bujur sama sekali tidak valid. Untungnya, garis lintang baik-baik saja sehingga dengan menggunakan peta saya dapat mengetahui berapa nilai yang benar pertama, menghitung, dan menghitung bahwa saya perlu mengurangi 4294.567548 dari setiap nilai untuk memperbaikinya. Satu-satunya batu sandungan yang saya miliki adalah bahwa metode ini tidak bekerja pada angka floating point, jadi saya hanya melakukan setiap sisi titik desimal sebagai substitusi terpisah, satu -4294 dan satu -567548.
Stuffe
7

Di Emacs (sejak versi 23): gunakan \,untuk mengeksekusi kode Lisp sewenang-wenang dalam penggantian regexp . Misalnya, untuk menyamakan angka yang bisa Anda gunakan

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

Di Vim: mulai teks pengganti Anda dengan \=(lihat :help sub-replace-special). Misalnya, untuk menyamakan angka:

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

Beberapa editor memungkinkan Anda untuk melakukan hal-hal semacam ini dengan makro: tentukan makro yang 1. mencari kecocokan berikutnya dan 2. melakukan penggantian (menggunakan alat eksternal untuk aritmatika jika perlu); ulangi makro sebanyak yang Anda cocok.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Jawaban yang diremehkan. Singkat dan Anda membahas 2 editor + case umum.
derekv
1

Anda dapat menggunakan vim untuk melakukannya untuk Anda. Cukup buka file Anda dan rekam makro . Contoh: Cari nomor apa saja

/[0-9]{1,}

lalu tekan q dan a (simpan makro di register a). Setelah itu, tekan Ctrl-X (menambah angkanya 1) dan tekan n (untuk hasil pencarian selanjutnya) sesudahnya. Setelah Anda melakukannya, tekan q lagi untuk menyimpan makro. Sekarang Anda dapat menerapkan makro ke nomor berikutnya dengan menekan @ + a. Ini akan mengubah angka saat ini dan melompat ke yang berikutnya. Dengan mengulanginya atau menggunakan x @ a, Anda dapat mengulanginya x kali.

Yah, deskripsi itu mungkin tidak cukup untuk menunjukkan bagaimana hal itu bisa dilakukan. Lihat saja tutorial yang menjelaskan mekanisme makro di vim.

evnu
sumber
Bagaimana jika saya perlu mengubah angka bukan dengan 1 tetapi dengan satu juta? Atau mungkin menggunakan beberapa perkalian / pembagian?
serg
1
Sangat mudah jika Anda ingin menambahkan konstanta x ke setiap angka: x + Ctrl + a. Apakah Anda perlu menambahkan nomor yang berbeda?
evnu