Ubah sed regex ke vim regex

Sep 09 2020

Saya mendapatkan sed regex ini yang saya temukan:

sed '/start/!d;s//&\n/;s/.*\n//;:a;/end/bb;$!{n;ba};:b;s//\n&/;P;D'

yang pada dasarnya mengeluarkan konten yang berada di antara titik awal dan titik akhir.

##1##
this is a test
with multiple
line
##z##

dan mengganti startdengan ##1##, dan enduntuk ##z##akan memberikan:


this is a test
with multiple
line

Jika ada beberapa kemunculan dari ##1##dan ##z##, maka itu jelas akan menampilkan semua teks di antara kejadian tersebut, seperti:

##1##
this is a test
with multiple
line
##z##
##1##
this is a test
with multiple
line
##z##

untuk


this is a test
with multiple
line


this is a test
with multiple
line

Untuk memperjelas lebih lanjut:

##1##
this is a test
with multiple
line
##z##
##2##
test
##z##

jelas hanya akan memberikan apa yang ditentukan sebagai titik awal (karena titik akhir ##z##selalu sama). Jadi jika saya menggunakan ##2##sebagai titik awal:


test

Ini akan memberikan yang di atas sebagai output.

Tujuan saya adalah untuk mengubahnya menjadi regex yang kompatibel untuk vim. Saya menggunakan situs ini dan panduan lokal sebagai bantuan, tetapi saya tidak yakin harus mulai dari mana untuk mengonversi yang di atas ke vim regex.

Jawaban

2 D.BenKnoble Sep 10 2020 at 03:16

Fungsi yang sangat sederhana yang melakukan pekerjaan dengan lebih idiomatis:

function! Between(start, end) abort
  let [start_line, _] = searchpairpos(a:start, '', a:end, 'bWn')
  let [end_line, _] = searchpairpos(a:start, '', a:end, 'Wn')
  if start_line is# 0 || end_line is# 0
    return
  endif
  call setline(start_line, '') " or: execute start_line 'delete'
  call setline(end_line, '') " or: execute end_line 'delete'
endfunction

Beri nama apa pun yang Anda inginkan, lalu lakukan, misalnya,

call Between('##1##', '##z##')

(yang bisa Anda ikat ke sebuah kunci, mungkin).

Untuk mengerjakan seluruh file, Anda mungkin dapat menggunakan :global(atau bahkan hanya :%call Between(...)), atau Anda mungkin memerlukan loop yang membungkus fungsi ini dan melintasi file. Dalam kasus yang terakhir, saya akan menggunakan search(a:start)untuk menemukan awal berikutnya dan kemudian +berada di dalam wilayah bersarang; maka saya akan memanggil fungsinya. Ini lebih cepat daripada memanggil fungsi di setiap baris.

3 Quasímodo Sep 10 2020 at 04:17
:g/END\|\%^/,/START\|\%$/s/.*//

Perintah global ini menandai semua baris yang cocok ENDatau awal file ( \%^). Kemudian ia melanjutkan untuk menghapus semuanya mulai dari baris yang ditandai hingga STARTatau akhir file ( \%$) dengan menggunakan perintah substitusi s/.*//.

Contoh berdampingan:

Before           |After
________________________________
test             |
START            |
this is a test   |this is a test
with multiple    |with multiple
line             |line
END              |
0                |
START            |
0101             |0101
END              |
11               |
111              |

Jika Anda tidak menginginkan baris kosong, Anda bisa mengganti s/.*//dengan ddi perintah global.

3 D.BenKnoble Sep 10 2020 at 06:31

Hanya untuk bersenang-senang, ingatlah Anda selalu bisa melakukannya

:%!sed '/start/\!d;s//&\n/;s/.*\n//;:a;/end/bb;$\!{n;ba};:b;s//\n&/;P;D'

Dan itu masih “vim”: P