Convertir sed regex en vim regex
J'ai cette regex sed que j'ai trouvée:
sed '/start/!d;s//&\n/;s/.*\n//;:a;/end/bb;$!{n;ba};:b;s//\n&/;P;D'
qui produit essentiellement le contenu entre un point de départ et un point final.
##1##
this is a test
with multiple
line
##z##
et le remplacement startavec ##1##et endpour ##z##cela donner:
this is a test
with multiple
line
S'il y a plusieurs occurrences du ##1##et ##z##, alors il afficherait évidemment tout le texte intermédiaire de ladite occurrence, comme ceci:
##1##
this is a test
with multiple
line
##z##
##1##
this is a test
with multiple
line
##z##
à
this is a test
with multiple
line
this is a test
with multiple
line
Pour clarifier encore plus:
##1##
this is a test
with multiple
line
##z##
##2##
test
##z##
ne donnerait évidemment que ce qui est spécifié comme point de départ (puisque le point final ##z##est toujours le même). Donc, si j'utilise à la ##2##place comme point de départ:
test
Cela donnerait ce qui précède comme sortie.
Mon objectif est de convertir ceci en une expression régulière compatible pour vim. J'utilise ce site et le manuel local comme aide, mais je ne sais pas par où commencer pour convertir ce qui précède en vim regex.
Réponses
Une fonction extrêmement simple qui fait le travail de manière beaucoup plus idiomatique:
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
Nommez-le comme vous voulez, puis faites, par exemple,
call Between('##1##', '##z##')
(que vous pourriez peut-être lier à une clé).
Pour travailler sur l'ensemble du fichier, vous pouvez peut- être utiliser :global(ou même simplement :%call Between(...)), ou vous pouvez avoir besoin d'une boucle enveloppant cette fonction et parcourant le fichier. Dans le cas de ce dernier, j'utiliserais search(a:start)pour trouver le prochain début et ensuite +pour être à l'intérieur de la région imbriquée; alors j'appellerais la fonction. C'est plus rapide que d'appeler la fonction sur chaque ligne.
:g/END\|\%^/,/START\|\%$/s/.*//
Cette commande globale marque toutes les lignes correspondant ENDou le début de file ( \%^). Ensuite, il procède à tout supprimer des lignes marquées jusqu'à STARTla fin de file ( \%$) ou à la fin en utilisant la commande de substitution s/.*//.
Un exemple côte à côte:
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 |
Si vous ne voulez pas de lignes vides, vous pouvez les remplacer s/.*//par ddans la commande globale.
Juste pour le plaisir, souviens-toi que tu peux toujours faire
:%!sed '/start/\!d;s//&\n/;s/.*\n//;:a;/end/bb;$\!{n;ba};:b;s//\n&/;P;D'
Et c'est toujours «vim»: P