Comment puis-je correspondance à plusieurs reprises de A jusqu'à B dans VIM?
-
09-09-2019 - |
Question
Je dois obtenir tout le texte entre <Annotation>
et </Annotation>
, où un mot MATCH
se produit. Comment puis-je faire dans VIM?
<Annotation about="MATCH UNTIL </Annotation> " timestamp="0x000463e92263dd4a" href=" 5raS5maS90ZWh0YXZha29rb2VsbWEvbGFza2FyaS8QyrqPk5L9mAI">
<Label name="las" />
<Label name="_cse_6sbbohxmd_c" />
<AdditionalData attribute="original_url" value="MATCH UNTIL </Annotation> " />
</Annotation>
<Annotation about="NO MATCH" href=" Cjl3aWtpLmhlbHNpbmtpLmZpL2Rpc3BsYXkvbWF0aHN0YXRLdXJzc2l0L0thaWtraStrdXJzc2l0LyoQh_HGoJH9mAI">
<Label name="_cse_6sbbohxmd_c" />
<Label name="courses" />
<Label name="kurssit" />
<AdditionalData attribute="original_url" value="NO MATCH" />
</Annotation>
<Annotation about="MATCH UNTIL </ANNOTATION> " score="1" timestamp="0x000463e90f8eed5c" href="CiZtYXRoc3RhdC5oZWx zaW5raS5maS90ZWh0YXZha29rb2VsbWEvKhDc2rv8kP2YAg">
<Label name="_cse_6sbbohxmd_c" />
<Label name="exercises_without_solutions" />
<Label name="tehtäväkokoelma" />
<AdditionalData attribute="original_url" value="MATCH UNTIL </ANNOTATION>" />
</Annotation>
La solution
Est-il doivent se faire dans vim? Pourriez-vous tricher, et ouvrir une deuxième fenêtre dans laquelle vous redirigez quelque chose en plus / moins que vous dit ce numéro de ligne pour aller à l'intérieur vim?
- modifier -
Je ne l'ai jamais fait un match / recherche multi-ligne vi [m]. Cependant, pour tricher dans une autre fenêtre:
perl -n -e 'if ( /<tag/ .. /<\/tag/)' -e '{ print "$.:$_"; }' file.xml | less
affiche les éléments / blocs pour « tag » (ou tout autre nom correspondant à plus), les numéros de ligne, en moins, et vous pouvez ensuite rechercher l'autre texte dans chaque bloc.
Assez proche?
- modifier -
dans les "moins", tapez
/MATCH
pour rechercher des occurrences de MATCH. Sur la marge de gauche sera le numéro de ligne où cette instance (dans les éléments ciblés / balises) est.
à l'intérieur vi [m], le type
:n
où "n" est le numéro de ligne souhaité.
Bien sûr, si ce que tu voulais vraiment faire était une sorte de recherche / Yank / remplacer, il est plus compliqué. À ce moment-là, awk / perl / rubis (ou quelque chose de similaire qui répond à vos goûts ... ou xsl?) Est vraiment l'outil que vous devez utiliser pour la transformation.
Autres conseils
Tout d'abord, un avertissement: Toute tentative de couper et XML dés avec des expressions régulières est fragile; un véritable analyseur XML ferait mieux.
Le schéma:
\(<Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>\)\@<=\(\(<\/Annotation\)\@!\_.\)\{-}"MATCH\_.\{-}\(<\/Annotation>\)\@=
Brisons le bas ...
Groupe 1 est <Annotation\(\s*\w\+="[^"]\{-}"\s\{-}\)*>
. Il correspond à la balise de début de l'élément d'attribut. Le groupe 2, qui est intégré dans le Groupe 1, correspond à un attribut et peut être répété 0 fois ou plus.
Groupe 2 est \s*\w\+="[^"]\{-}"\s\{-}
. La plupart de ces pièces sont couramment utilisés; le plus insolite est \{-}
, ce qui signifie que la répétition non gourmand (*?
dans les expressions régulières Perl compatibles). Le match des espaces non-gourmand à la fin est importante pour la performance; sans elle, Vim essaiera tous les moyens possibles de diviser l'espace entre les attributs entre les \s*
à la fin du groupe 2 et le \s*
au début de la prochaine occurrence du groupe 2.
Groupe 1 est suivi par \@<=
. Ceci est un facteur positif zéro largeur regarder en arrière. Il empêche la balise de début d'être inclus dans le texte correspondant (par exemple, pour s ///).
Groupe 3 est \(<\/Annotation\)\@!\_.
. Il comprend le groupe 4, qui correspond au début de l'attribut balise de fin. Le \@!
est une anticipation négative zéro largeur et \_.
correspond à tout caractère (y compris les nouvelles lignes). Ensemble, ces groupes correspond à tout caractère sauf si l'attribut balise de fin commence. Groupe 3 est suivi d'un marqueur de répétition non avide \{-}
afin qu'il corresponde le plus petit bloc de texte avant MATCH. Si vous deviez utiliser \_.
au lieu du groupe 3, le texte correspondant pourrait inclure la balise de fin d'un élément d'annotation qui a fait pas comprennent MATCH JUSQU dans l'élément suivant Annotation avec MATCH. (Essayez.)
Le bit suivant est simple: Trouver MATCH et un nombre minimal d'autres caractères avant la balise de fin
. Groupe 5 est facile: Il est la balise de fin. \@=
est un regard vert positif zéro largeur, qui est inclus ici pour la même raison que le \@<=
pour la balise de début. Nous devons répéter <\/Attribute
plutôt que d'utiliser \4
parce que les groupes modificateurs zéro largeur ne sont pas pris.