2010-11-16 20 views
15

So che si tratta di un campo lungo, ma ho un enorme file di testo e ho bisogno di aggiungere un numero dato ad altri numeri che corrispondono ad alcuni criteri.Ricerca e sostituzione Vim, aggiunta di una costante

Es.

identifying text 1.1200 
identifying text 1.1400 

e mi piacerebbe trasformare questo (con l'aggiunta di dire 1.15)

identifying text 2.2700 
identifying text 2.2900 

Normalmente avrei fatto questo in Python, ma è su una macchina Windows in cui non posso installare troppe cose. Ho Vim però :)

risposta

16

Ecco una semplificazione e di una correzione sulla soluzione di Hobbs:

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

Grazie a \zs, non c'è bisogno di ricordare il testo principale. Grazie a str2float() viene eseguita una singola aggiunta sull'intero numero (in altre parole, 1.15 + 2.87 darà il risultato previsto, 4.02 e non 3.102).

Naturalmente questa soluzione richiede una versione recente di Vim (7.3?)

+0

+1. * I * può anche farlo funzionare (e questo è molto) ma esiste un modo per mantenere gli zero finali. –

+2

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

+1

Alcune cose che ho dovuto cercare: '\ =' consente la stringa sostitutiva per essere un'espressione. ([collegamento] (http://vim.wikia.com/wiki/Using_an_expression_in_substitute_command)) –

1

Per gli interi si può semplicemente utilizzare n^A per aggiungere n ad un numero (e n^X per sottrarlo). Dubito però che funzioni per numeri frazionari.

+2

E funziona ma facendo così, OP ha bisogno di 1501 n^A. –

3

Il formato del numero sembra essere fisso, quindi è facile convertire in int e tornare indietro (rimuovere il punto) aggiungere 11500 e rimettere il punto.

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

Se non si vuole fare che su tutte le linee, ma solo quella che incontro 'l'identificazione del testo' sostituire tutto il% per 'g/text identificando /'

10

si può fare un catturando regex e quindi utilizzare un'espressione vimscript come una sostituzione, qualcosa come

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

(solo senza l'interruzione di riga).

1

Beh questo non potrebbe essere una soluzione per vim, ma penso che awk può aiutare:

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

e il test

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

avevo bisogno di LC_ALL = C per la corretta conversione del galleggiante punto separatore e forse c'è una soluzione più elegante per stampare l'inizio/il resto della stringa. E il risultato è simile:

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

Dam!Basta leggere che è una macchina Windows, quindi dimenticarsi di awk: D – joecks

+0

Grazie ancora. Non sai mai quando potrebbe essere utile ... –

1

Utilizzando 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' 

se si dispone di 300 linee con questo modello solo ora facendo

[email protected] 
+0

L'OP desidera incrementare un numero (" ** a ** numero dato "<- singolare) con 1.15 e non due numeri separati. –

Problemi correlati