2009-09-21 10 views
25

Ho un file con circa 1000 righe. Tutte le righe iniziano con un numero di sette cifre, ad eccezione della linea occasionale. Ho bisogno di prendere queste linee e in realtà unirmi a loro con la linea precedente.Come faccio a convincere Vim ad abbinare una linea che non inizia con un numero di sette cifre?

Sono riuscito a essere in grado di adattarsi a qualsiasi riga che inizia con un numero a sette cifre utilizzando il seguente schema di espressione regolare:

^\d\{7} 

non posso sembrare convincerlo a tutte le linee che non corrisponde allo questo modello, che è davvero quello che sto cercando.

Come seconda domanda che inserirò in questo. È possibile avere linee che corrispondono (o non corrispondono per rimanere coerenti con quello che sto cercando di fare) di unirsi alla linea precedente (al contrario del comando J che porta la riga successiva fino al quello attuale)?

Grazie

risposta

30
^\(\d\{7}\)\@! 

Questa è la sintassi regex di vim per un lookahead negativo.

Se stai facendo questo come un comando di massa :, si dovrebbe essere in grado di fare proprio

:v/^\d\{7}/-1j 
+0

Stranamente, entrambi hanno come risultato la stessa cosa. Anche se per me non ha senso che quello senza il^sta effettivamente funzionando, no che ci penso. –

+0

L'unica differenza è che quella senza la^corrisponderà se c'è un numero di sette cifre in un'altra posizione sulla linea diversa dall'iniziale. – chaos

+0

Ah, sì capisco. In questo caso non c'era, quindi nessuna riga aggiuntiva è stata modificata ... spiega perché il conteggio di un minor numero di linee era esattamente lo stesso. –

6

Anche l'espressione regolare

^\(\d\{7}\)\@! 

sarà invertire l'espressione originale. Per maggiori informazioni su questa sintassi, vedere qui:

:help \@! 

Per quanto riguarda il secondo problema, si potrebbe ad esempio sostituire il newline finale sulle linee precedenti con nulla:

:%s/$\n^\(\d\{7}\)\@!//g 
+0

Questo era vicino, ma il join dell'altra risposta lasciava uno spazio tra le linee che erano unite insieme (che in realtà è ciò di cui ho bisogno). Questo esempio mette l'ultimo carattere dalla prima linea direttamente prima del primo carattere dalla riga successiva. Questo è un effetto collaterale che devo evitare. Ancora, +1 per la tua risposta e grazie. –

+0

Oh bene! Lo spazio può essere aggiunto in questo modo::% s/$ \ n^\\ (\ d \ {7} \\) \ @!// G – tobiasvl

+0

Abbastanza vero. L'altro è più corto e io sono pigro; P –

1

ecco la mia soluzione utilizzando awk, che può essere chiamato all'interno vim:

$ cat seven.awk 
# Script to join lines that does not start with 7 digits 
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9]/ { print; next } 
{ printf $0; getline; print } 

$ cat seven.txt 
123 
4579 bad 
7654321 This line is OK 
1234567 OK So is this 
111 
2222 bad again 
4443333 OK again 

$ awk -f seven.awk seven.txt 
1234579 bad 
7654321 This line is OK 
1234567 OK So is this 
1112222 bad again 
4443333 OK again 

Chiedo scusa per la mia espressione goffo: il mio awk è vecchio e non capisce l'espressione di fantasia come: \ d {7}. Se si vuole invocare questo comando dall'interno vim per l'intero file:

:%!awk -f seven.awk 
+0

Originariamente avevo [0-9] anche sette volte. Mi ha fatto molto piacere che l'ex editor di gVim abbia permesso la combinazione \ d {7}. –

9

Ora, per la vera risposta

L'espressione regolare che corrisponde a stringhe che non iniziano con 7 cifre è molto semplice :

.{0,6}([^0-9].*)? 

un più classico equivalente espressione regolare senza {} sintassi è in realtà più leggibile: ci mostra visivamente ciò che sta accadendo:

(|.|..|...|....|.....|......)([^0-9].*)? 

I.e. corrispondenza tra 0 e 6 caratteri che può essere qualsiasi cosa, opzionalmente seguita da un nondigit che, se si verifica, può essere seguito da zero o più caratteri aggiuntivi. Ciò garantisce che se una stringa contiene sette caratteri o più caratteri, almeno uno dei primi sette caratteri è un non condito.

Per tradurre questo per corrispondenza linee in Vim, aggiungiamo un po 'di fuga e di ancoraggio:

^.\{0,6\}\([^0-9].*\)\?$ 

non mi "faccio" \d; è troppo nuovo di moda. :)

+0

A proposito, ho incrociato le dita quando ho scritto quell'ultima riga e ho prodotto questo commit nello stesso mese: http://www.kylheku.com/cgit/txr/commit/?id=e63c7be49e144d2ed3967c28243109342e17dcaa – Kaz

Problemi correlati