J'ai un cas d'utilisation commun lorsque je transforme une expression python de la manière suivante:
value 1
value 2
value 3
dans
['value 1', 'value 2', 'value 3']
La façon la plus simple peut être d'utiliser un mappage, mais je voulais utiliser une substitution pour cette tâche.
Jusqu'à présent, j'ai eu:
s/\(.*\n\)\+/[&]/g
Ce qui se traduit par
[value 1
value 2
value 3
]
Cela soulève une question, car je veux pouvoir faire correspondre le \(.*\)
, mais pas le \n
et utiliser le résultat du matched dans un '...'
.
Sais-tu comment faire cela?
:'<,'>s/\v(.*)\n/'\1', / | s/\v(.*), /[\1]/
vous pouvez transformer cela en un mappage visuel:xnoremap ,x :s/\v(.*)\n/'\1', / <Bar> s/\v(.*), /[\1]/<CR>
et peut-être en un mappage normal si le expression est à l'intérieur d'un paragraphe:nnoremap ,x :'{+1,'}-1s/\v(.*)\n/'\1', / <Bar> s/\v(.*), /[\1]/<CR>
Voici le mappage,x
.:%! echo "[$(sed "s/.*/'&',/" % | tr '\n' ' ' | sed 's/, $//')]"
Réponses:
Éditer
Il est possible de le faire en une seule expression si nous utilisons une "expression de remplacement secondaire". Voir en bas pour plus d'informations à ce sujet.
/Éditer
Le problème ici est que vous voulez faire deux choses différentes.
Opérer sur le match dans son ensemble (c'est-à-dire l'entourer de
[]
)Opérer sur chaque élément du match (c'est-à-dire les entourer de
'',
)Vous pouvez facilement faire l'un ou l'autre:
:s/\(.\+\n\)\+/[&]/
:%s/\(.\+\)\n/'\1', /
mais pour autant que je sache, il n'y a aucun moyen de faire les deux en une seule opération. J'ai essayé d'obtenir la sortie appropriée avec quelque chose comme:
Mais bien sûr, le problème avec cela est que la
\2
correspondance ne correspond qu'à la dernière correspondance du deuxième ensemble de parenthèses mémoire\(\)
et ne se "souvient" de rien avant cela. Vous vous retrouvez donc avec seulement la dernière ligne.Je recommanderais de faire un pré / post-traitement avec une
:s///
commande supplémentaire pour se débarrasser des nouvelles lignes avant / après le fait. Voici ce que j'ai trouvé1ère ligne (Supprimer les nouvelles lignes)
.,/\n^$/
Il s'agit d'un modificateur de plage pour la recherche et le remplacement. Sans cela, la commande continuera à mutiler votre fichier entier. Actuellement, il passe de la ligne actuelle.
à la ligne vierge suivante\n^$
. Je ne sais pas comment vous aviez l'intention de diviser les choses, mais vous avez besoin d'un moyen de lui dire d'arrêter.s/
Le début d'une commande de recherche et remplacement\(.*\)\n
Faites correspondre la ligne entière, mais enregistrez uniquement la partie sans la nouvelle ligne.'\1',
Remplacez la ligne par la correspondance entourée de guillemets simples et ajoutez une virgule.2e ligne (Surround entre parenthèses)
\(.*\),
Correspond à la ligne entière mais pas à la dernière virgule et espace[\1]
Entourez de crochets et supprimez également la virgule de fin superflue et l'espace.Je vais continuer à chercher, mais pour le moment je ne pense pas que ce soit possible avec une seule expression. :(
ÉDITER:
J'ai trouvé un moyen de le faire avec une seule expression! En interne, il s'agit en fait de deux substitutions, mais il s'agit techniquement d'une seule expression. Voici ce que j'ai trouvé:
:s///
: Faites une substitution\v((.+\n)*.+)\n
: Rassemble essentiellement toutes les lignes non vides suivantes et les stocke toutes sauf la finale\n
\=
Permet d'utiliser une expression dans le remplacement (voir:h sub-replace-expression
)substitute(submatch(1)...)
: Remplace tous ceux stockés\n
par', '
"['" . ... . "']"
: Ajoute['
et ajoute']
Cela commencera à la position du curseur et ira jusqu'à ce qu'il trouve une ligne vierge (
^\n
). Ne pas saisir le dernier\n
est important car sans ce bit, nous nous retrouvons avec un autre',
que nous ne voulons pas à la fin.Certains pourraient considérer cela comme plus complexe que la réponse à deux expressions précédente. Mais j'ai pensé que j'irais de l'avant et ajouterais cela car il est en fait possible de le faire avec une seule expression. :)
la source
Surlignez visuellement, puis:
Il entoure chaque ligne, pour faire par exemple
['value 1']
, les joint toutes, puis remplace les espaces adjacents]
et[
par des virgules.La documentation de
*
in*j!
est à:help cpo-star
propos. Celui-là est un peu difficile à trouver.la source
:'<,'>s/\v(.*)(\_.)/['\1']/
et supprimer la jointure.\n
, c'est pourquoi j'ai utilisé:join
. J'aurais probablement dû le mentionner. :-)'<,'>s/.*/['&']/ | *s/]\_.\[/, /
alors?*s/]\n\[/, /e
.