Vim equivalente all'espressione regolare Perl per fare una sostituzione in una sostituzione?

Aug 25 2020

Ho questa regex perl:

s/(^(#+)\s.*?\g2)/$1 =~ s|\n| |rg/gmse

Elimina tutte le nuove linee tra i ##+personaggi e le sostituisce con uno spazio. Ci vorrà una stringa come:

before text
more text
### hjh jh ja jhjasdhf jh'j
asdk kas dkjakdjf kasjd fkjasdkfj
kajsdkjf kasjdf end ###
after text

e modificalo in:

before text
more text
### hjh jh ja jhjasdhf jh'j asdk kas dkjakdjf kasjd fkjasdkfj kajsdkjf kasjdf end ###
after text

Voglio fare lo stesso con vim. Ho scoperto che posso usare \=per trasformare il lato destro in un'espressione, ma come faccio a eseguire una sostituzione sul valore di \ 1 e stamparla?

%s/\v(^(#+)\s.*?\g2)/\= WHAT GOES HERE?/g

Risposte

2 filbranden Aug 25 2020 at 03:33

È possibile utilizzare la substitute()funzione per eseguire una sostituzione del testo sul lato di sostituzione di un :scomando. E puoi utilizzare submatch()per avere accesso ai gruppi abbinati, anche submatch(0)per l'intera partita.

È inoltre necessario utilizzare la sintassi Vim corretta per la regex, che differisce dalla sintassi Perl in alcuni modi. Dovresti usare {-}invece di *?per una ripetizione non avida, \2invece di \g2abbinare la stessa identica stringa abbinata nel gruppo 2, e devi anche \_.abbinare qualsiasi carattere incluso il ritorno a capo.

In realtà, poiché puoi usare la corrispondenza completa, non hai bisogno del gruppo di cattura esterno, quindi puoi sbarazzarti anche di quel set di parentesi e usarlo \1per abbinare la sequenza di #s.

Mettere tutto insieme:

:%s/\v^(#+)\s\_.{-}\1/\=substitute(submatch(0), '\n', ' ', 'g')/
4 JürgenKrämer Aug 26 2020 at 14:13

Nel caso in cui si volessero unire le righe e si usassero solo espressioni regolari perché è la scelta "naturale" in Perl, c'è un altro modo in Vim. Puoi combinare il :globale il :joincomando per unire tutte le linee tra due sequenze di hash:

g/#\+/;/#\+/ join