2010-11-16 9 views
15

Je sais que c'est un plan long, mais j'ai un énorme fichier texte et j'ai besoin d'ajouter un nombre donné à d'autres numéros correspondant à certains critères.Vim rechercher et remplacer, en ajoutant une constante

Par exemple.

identifying text 1.1200 
identifying text 1.1400 

et je voudrais transformer ce (en ajoutant dire 1,15) à

identifying text 2.2700 
identifying text 2.2900 

Normalement, je ferais ceci en Python, mais il est sur une machine Windows où je ne peux pas installer trop de choses. J'ai bien :) Vim

Répondre

16

Voici une simplification et une solution sur la solution de hobbs:

:%s/identifying text \zs\d\+\(.\d\+\)\=/\=(1.15+str2float(submatch(0)))/ 

Merci à \zs, il n'y a pas besoin de rappeler le texte de référence. Merci à str2float() une seule addition est faite sur le nombre entier (en d'autres termes, 1.15 + 2.87 donnera le résultat attendu, 4.02, et non 3.102).

Bien sûr, cette solution nécessite une version récente de vim (7.3?)

+0

+1. * I * peut même faire fonctionner ceci (et c'est beaucoup dire) mais y a-t-il un moyen de conserver le zéro final. –

+2

Avec 'printf()' peut être? (: h printf()) -> '... \ = printf ('%. 4f', 1.15 + str2float (......))' –

+1

Une chose que je devais rechercher: '\ =' permet la chaîne de remplacement est une expression. ([link] (http://vim.wikia.com/wiki/Using_an_expression_in_substitute_command)) –

1

Pour les entiers vous pouvez simplement utiliser n^A ajouter n à un certain nombre (et n^X soustrayez). Je doute que cela fonctionne bien pour les nombres fractionnaires.

+2

Il fonctionne mais en faisant cela, OP a besoin de 1501 n^A. –

3

Votre format de nombre semble être fixe, il est donc facile de convertir en int et revenir (supprimer le point) ajouter 11500 et remettre le point.

:%s/\.// 
:%normal11500^A " type C-V then C-a 
:%s/....$/.&/ 

Si vous ne voulez pas faire cela sur toutes les lignes, mais seulement celui qui rencontre « identifiant texte » remplacer tous les% en « g/texte indentifying/»

10

Vous pouvez faire la capture regex, puis utiliser une expression vimscript comme un remplacement, quelque chose comme

:%s/\(identifying text \)\(\d\+\)\.\(\d\+\)/ 
    \=submatch(1) . (submatch(2) + 1) . "." . (submatch(3) + 1500) 

(seulement sans le linebreak).

1

Eh bien cela pourrait ne pas être une solution pour vim mais je pense que awk peut aider:

cat testscript | LC_ALL=C awk '{printf "%s %s %s %s %.3f\n", $1,$2,$3,$4,$5+1.567 }' 

et le test

this is a number 1.56 
this is a number 2.56 
this is a number 3.56 

je avais besoin LC_ALL = C pour la conversion correcte du flottant séparateur de points, et peut-être il y a une solution plus élégante pour imprimer le début/reste de la chaîne. Et le résultat ressemble à:

this is a number 3.127 
this is a number 4.127 
this is a number 5.127 
+0

Mère!Il suffit de lire que c'est une machine Windows, alors oubliez awk: D – joecks

+0

Merci encore. Vous ne savez jamais quand cela pourrait être utile ... –

1

Utiliser macro

qa .......................... start record macro 'a' 
/iden<Enter> ................ search 'ident*' press Enter 
2w .......................... jump 2 words until number one (before dot) 
Ctrl-a ...................... increases the number 
2w .......................... jump to number after dot 
1500 Ctrl-a ................. perform increases 1500 times 
q ........................... stop record to macro 'a' 

si vous avez 300 lignes avec ce modèle juste en train de faire

[email protected] 
+0

L'OP veut incrémenter un nombre (" ** un ** nombre donné "<- singulier) avec 1.15, et non deux nombres séparés. –