Sed regex'i vim regex'e dönüştürme

Sep 09 2020

Bulduğum bu eski normal ifadeyi aldım:

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

temelde bir başlangıç ​​noktası ile bir bitiş noktası arasındaki içeriği çıkarır.

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

ve değiştirme startile ##1##ve endhiç ##z##verecekti:


this is a test
with multiple
line

Birden fazla kopyasını varsa ##1##ve ##z##o zaman tabii ki gösterecek aradaki tüm söyleyen bir oluşum, şöyle metni:

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

-e


this is a test
with multiple
line


this is a test
with multiple
line

Daha da netleştirmek için:

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

açıkça sadece başlangıç ​​noktası olarak belirtilenleri verir (çünkü bitiş noktası ##z##her zaman aynıdır). Yani ##2##bunun yerine başlangıç ​​noktası olarak kullanırsam :


test

Bu, yukarıdakileri çıktı olarak verir.

Amacım bunu vim için uyumlu bir regex'e dönüştürmektir. Ben kullanıyorum bu siteyi nereye vim regex için yukarıdaki dönüştürmek için başlamak için ben emin değilim ve yardım gibi yerel kılavuzu ama.

Yanıtlar

2 D.BenKnoble Sep 10 2020 at 03:16

İşi çok daha deyimsel olarak yapan son derece basit bir işlev:

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

Ne istersen adlandır ve sonra yap, örneğin,

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

(belki de bir anahtara bağlayabilirsiniz).

Bütün dosya üzerinde çalışması için, belki kullanabilmek için :global(hatta sadece :%call Between(...)) veya bir döngü bu işlevi sarma ve dosyayı kateden gerekebilir. İkincisi durumunda search(a:start), bir sonraki başlangıcı bulmak ve sonra +iç içe geçmiş bölgenin içinde olmak için kullanırım; o zaman işlevi çağırırdım. Bu, işlevi her satırda çağırmaktan daha hızlıdır.

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

Bu global komut, eşleşen tüm satırları ENDveya dosyanın ( \%^) başlangıcını işaretler . Ardından , ikame komutunu kullanarak işaretli satırlardan STARTdosyanın sonuna ( \%$) kadar veya sonuna kadar olan her şeyi silmeye devam eder s/.*//.

Yan yana bir örnek:

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              |

Eğer boş satırlar istemiyorsanız, o kadar değiştirebileceğiniz s/.*//tarafından dküresel komuta.

3 D.BenKnoble Sep 10 2020 at 06:31

Sadece eğlence için, her zaman yapabileceğini unutma

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

Ve bu hala "vim": P