2011-06-21 6 views
8

Esta pregunta es casi idéntica a this question, excepto que tengo que ir a tres espacios (directrices de codificación de la empresa) en lugar de a cuatro y la solución aceptada solo duplicará el patrón coincidente. Aquí estaba mi primer intento:¿Cómo volver a formatear un archivo fuente para pasar de 2 espacios a 3?

:%s/^\(\s\s\)\+/\1 /gc 

Pero esto no funciona porque cuatro espacios se reemplazan por tres. Así que creo que lo que necesito es una forma de calcular cuántas veces el patrón coincide con "+" y usar ese número para crear el otro lado de la sustitución, pero creo que esta funcionalidad probablemente no esté disponible en la expresión regular de Vim (Let yo sé si crees que podría ser posible).

También he intentado hacer la sustitución de forma manual mediante la sustitución de los guiones más grandes primero y luego el siguiente guión más pequeña hasta que llegué todo convertida pero esto era difícil seguir la pista de los espacios:

:%s/^    \(\S\)/      \1/gc 

podría enviar a través de Perl, ya que parece que Perl podría tener la capacidad de hacerlo con su Extended Patterns. Pero no pude hacer que funcionara con mi versión de Perl. Aquí fue mi intento de tratar de contar una de:

:%!perl -pe 'm<(?{ $cnt = 0 })(a(?{ local $cnt = $cnt + 1; }))*aaaa(?{ $res = $cnt })>x; print $res' 

Mi último recurso será escribir un script en Perl para hacer la conversión, pero yo tenía la esperanza de una solución más general en Vim para que pudiera volver a utilizar la idea resolver otros problemas en el futuro

+0

Es posible;) – Amadan

+0

Gracias Amadan, marcado como respuesta correcta. Me pregunto si alguien me puede mostrar cómo se vería la solución si se enviara a través de Perl regex, ya que podría tener la necesidad de hacerlo en un script. – stephenmm

+0

Relacionado: [Re-sangría de código con sangría grave] (http://vi.stackexchange.com/q/236/467) en Vim SE – kenorb

Respuesta

7

Deje que vim lo haga por usted?

:set sw=3<CR> 
gg=G 

El primer comando establece la opción shiftwidth, que es la cantidad que sangría. La segunda línea dice: ve a la parte superior del archivo (gg) y reinicia (=) hasta el final del archivo (G).

Por supuesto, esto depende de que vim tenga un buen formateador para el idioma que está utilizando. Algo podría estropearse si no.

manera Regexp ... Más seguro, pero menos comprensible:

:%s#^\(\s\s\)\+#\=repeat(' ',strlen(submatch(0))*3/2)#g 

(que tenía que hacer un poco de experimentación.)

dos puntos:

  • Si la sustitución se inicia con \= , se evalúa como una expresión.
  • Puede usar muchas cosas en lugar de /, entonces / está disponible para la división.
+0

¡Las cosas de ancho de cambio realmente distorsionaron mi archivo pero la expresión regular funcionó perfectamente! ¡Gracias! Intenté buscar ayuda en vim para obtener más información sobre el '\ =' pero no estoy seguro de qué buscar en la ayuda. ¿Podría indicarme la documentación que habla al respecto? – stephenmm

+2

': help sub-replace-expression' – phant0m

+0

Hay un comando': retab'. – ZyX

1

La versión de Perl que pidió ...

Desde la línea de comandos (ediciones en el lugar, sin copia de seguridad):

bash$ perl -pi -e 's{^((?: )+)}{" " x (length($1)/2)}e' YOUR_FILE 

(en el lugar, original a la copia de seguridad " TU ARCHIVO.bak "):

bash$ perl -pi.bak -e 's{^((?: )+)}{" " x (length($1)/2)}e' YOUR_FILE 

De vim durante la edición de YOUR_FILE:

:%!perl -pe 's{^((?: )+)}{" " x (length($1)/2)}e' 

la expresión regular coincide con el principio de la línea, seguido por (el conjunto capturada de) uno o más "grupos de dos espaciales". El patrón de sustitución es una expresión perl (de ahí el modificador 'e') que cuenta el número de grupos de "dos espacios" que se capturaron y crea una cadena de ese mismo número de grupos de "tres espacios". presente en el original se conserva después de la sustitución. Por lo tanto, si tenía tres espacios antes, tendrá cuatro después, cinco antes se convertirá en siete después, etc.

+0

¡Genial, gracias Brian! – stephenmm

Cuestiones relacionadas