2010-11-16 4 views
15

Sé que esta es una posibilidad remota, pero tengo un gran archivo de texto y necesito agregar un número dado a otros números que coincidan con algunos criterios.Búsqueda y reemplazo de Vim, agregando una constante

Por ejemplo.

identifying text 1.1200 
identifying text 1.1400 

y me gustaría transformar esta (añadiendo decir 1.15) a

identifying text 2.2700 
identifying text 2.2900 

Normalmente me gustaría hacer esto en Python, pero es en una máquina Windows donde no puedo instalar demasiadas cosas. Tengo Vim aunque :)

Respuesta

16

Aquí es una simplificación y una solución en la solución de Hobbs:

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

Gracias a \zs, no hay necesidad de recordar el texto que lleva. Gracias a str2float() se realiza una sola adición en el número entero (en otras palabras, 1.15 + 2.87 dará el resultado esperado, 4.02, y no 3.102).

Por supuesto, esta solución requiere una versión reciente de Vim (7,3?)

+0

+1. * I * incluso puede hacer que esto funcione (y eso es mucho decir), pero ¿hay alguna manera de retener los cero finales? –

+2

Con 'printf()' puede ser? (: h printf()) -> '... \ = printf ('%. 4f', 1.15 + str2float (......))' –

+1

Algo que tuve que buscar: '\ =' permite la cadena de reemplazo es una expresión. ([link] (http://vim.wikia.com/wiki/Using_an_expression_in_substitute_command)) –

1

Para enteros sólo puede utilizar n^Una añadir n a un número (y n^X para restarlo). Sin embargo, dudo si eso funciona para números fraccionarios.

+2

funciona pero al hacerlo de esta manera, OP necesita 1501 n^A's. –

3

Su formato de número parece ser fijo, por lo que es fácil de convertir a int y volver (eliminar el punto) agregar 11500 y poner el punto de nuevo.

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

Si no quieres hacer eso en todas las líneas, pero sólo el que partido de 'la identificación de texto' reemplazar todos los% en 'g/texto identificando /'

10

se puede hacer una la captura de expresiones regulares y luego usar una expresión Vimscript como un reemplazo, algo así como

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

(sólo que sin el salto de línea).

1

bien esto podría no ser una solución para vim, pero creo que awk puede ayudar:

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

y la prueba

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

necesitaba el LC_ALL = C para la conversión correcta de la flota punto separador, y tal vez hay una solución más elegante para imprimir el principio/resto de la cadena. Y el resultado se parece a:

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

¡Presa!Acabo de leer que es una máquina de Windows, así que olvídate de awk: D – joecks

+0

Gracias todavía. Nunca se sabe cuándo esto podría ser útil ... –

1

Usando 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 tiene 300 líneas con este patrón ahora haciendo

[email protected] 
+0

El OP desea incrementar un número (" ** a ** número dado "<- singular) con 1.15, y no dos números separados. –

Cuestiones relacionadas