Lignes en double commençant par «x», remplaçant «x» dans le double par «y»?

9

J'ai un fichier avec le modèle suivant:

foo 111
baz
foo 222
baz
foo 333
baz

qui doit être transformé en

foo 111
bar 111
baz
foo 222
bar 222
baz
foo 333
bar 333
baz

Donc, dupliquez toutes les lignes commençant par fooet modifiez uniquement foole doublon mais laissez le reste de la ligne (qui diffère dans chaque cas) intact. Comment faire ça?

LB7979
la source
Si vous n'êtes pas lié par l'enfer sur une expression rationnelle, une macro fera très bien l'affaire. Peu importe vraiment dans des cas simples comme celui-ci, mais si vous avez quelque chose d'un peu plus compliqué, c'est une alternative très valable.
PhilippFrank

Réponses:

19

Voici:

:g/foo/t.|s//bar

Décomposition:

:g/foo/    " start a global command applied on all lines matching 'foo'
t.         " duplicate the current line (the cursor is now on the new line)
|          " chain a new command
s//bar     " substitute the last searched element with 'bar'

Parce que la gcommande mettra à jour le modèle de recherche, vous pouvez donc omettre le modèle à remplacer dans la commande de substitution. (ref:, :h :gchercher search pattern).


Ancienne version:

:g/foo/norm! yyp:s/foo/bar^M

Décomposition:

:g            start a global command
/foo/         apply only on lines having 'foo'
norm!         execute a normal command
yyp           duplicate the line
:s//bar       replace foo with bar on the line (the duplicated one)
^M            add enter to execute the substitution

Pour insérer la ^Mpresse Ctrl+vet enter.

Remarque : je suis à l'origine venu avec la "plus ancienne" version, avant d'apprendre la tcommande. Je vais le laisser mais je ne recommanderai pas de l'utiliser. Le premier est plus simple et plus propre.

nobe4
la source
Résolu, la «version plus simple» fonctionnait parfaitement. Cependant, la première version a eu pour résultat que la ligne en double commence toujours par foo....
LB7979
étrange, êtes-vous entré ^Mcomme je l'ai expliqué?
nobe4
Mon mauvais, n'a pas bien lu. La première solution fonctionne aussi!
LB7979
Je ne sais pas du tout pourquoi vous vous embêtez à inclure la version compliquée. La version la plus simple est ... plus simple. ;) (Sans parler de la conformité POSIX.) Pourquoi ne pas le mettre en premier?
Wildcard
1
Au départ, j'ai proposé la première version, qui était plus naturelle pour moi, car à l'époque je n'en avais pas conscience t, puis j'ai ajouté la seconde. Je vais changer l'ordre, tu as raison. Que diriez-vous du premier étant POSIX?
nobe4
1

Je fais des trucs comme ça tout le temps et je fais juste quelque chose comme %s/^foo \(.*\)/foo \1\rbar \1/(en partie parce que je fais aussi beaucoup de tâches similaires qui ne peuvent pas être transformées en quelque chose d'intelligent en utilisant une fonction de copie, et qui \(.*\)fait maintenant partie de ma mémoire musculaire).

Je soupçonne que ce n'est pas compatible POSIX (cela ne fonctionne pas sur d'autres clones vi), mais l'utilisation de ^M( C-VReturn) au lieu de \rsemble fonctionner sur la plupart des autres clones vi.

Aléatoire832
la source