2009-05-15 21 views
5

Tengo un gran número de archivos CSV que se parecen a esto a continuación:vim y archivo csv: poner información de la cabecera en una nueva columna


xxxxxxxx
xxxxx
envío, YD564n
xxxxxxxxx
xxxxx

1, RR1760
2, HI3503
3, HI4084
4, HI1824


que necesito para que se vean como los siguientes:


xxxxxxxx
xxxxx
envío, YD564n
xxxxxxxxx
xxxxx

YD564n, 1 , RR1760
YD564n, 2, HI3503
YD564n, 3, HI4084
YD564n, 4, HI1824


YD564n es un número de envío y será diferente para cada archivo csv. Pero siempre viene justo después de "Envío".

¿Qué comando (s) de vim puedo usar?

Respuesta

3

Puede hacerlo usando una macro y aplicándola sobre varios archivos.

Aquí hay un ejemplo. Escriba lo siguiente como está:

3gg$"ayiw:6,$s/^/<C-R>a/<CR>:w<CR>:bn<CR> 

Ahora que se ve horrendo. Déjame ver si puedo explicar eso un poco mejor.

3gg$: Ir al final de la tercera línea.

"ayiw: Copiar la última palabra en el registro a.

:6,$s/^/<C-R>a/<CR>: En cada línea a partir del 6 en adelante, reemplace al principio lo que esté en el registro a.

:w<CR>:bn<CR>: guarde y vaya al siguiente búfer.

Ahora se puede asignar este a una tecla, por

:nnoremap <C-A> 3gg$"ayiw:6,$s/^/<C-R>a/<CR>:w<CR>:bn<CR> 

Entonces, si usted tiene decir 200 archivos CSV, vim abierta como

vim *.csv 

y luego

200<C-A> 

Donde escribe Ctrl-A allí, y debería estar todo hecho.

Dicho esto, definitivamente me sentiría más cómodo haciendo esto en un lenguaje de scripting adecuado, sería mucho más directo.

4

En un tipo de archivo lo siguiente en modo normal:

qqgg/^Shipment,<CR>ww"ay$}j:.,$s/^/<C-R>a,<CR>q 

Tenga en cuenta que <CR> es la tecla ENTER, y <C-R> es Ctrl-R.

Esto actualizará ese archivo y recrd los comandos en el registro q.

Luego en cada otro tipo de archivo @q (también en modo normal). (Esto se reproducirá registro q)

2

Esto podría hacerse como una Perl de una sola línea:

perl -i.bak -e' $c = do {local $/; <>}; 
       ($n) = ($c =~ /Shipment,(\w+)/); 
       $c =~ s/^(\d+,)/$n,$1/gm; 
       print $c' shipment.csv 

Esto leer el contenido de shipment.csv en $c, extraer el ID de envío en $n, y anteponer cada CSV línea con el número de envío. El archivo se modificará in situ con una copia de seguridad guardada en shipment.csv.bak.

Para hacer esto desde dentro de Vim, se adaptan como un filtro:

:%!perl -e' $c = do {local $/; <>}; ($n) = ($c =~ /Shipment,(\w+)/); $c =~ s/^(\d+,)/$n,$1/gm; print $c' 
1

Bueno, no me Bash, pero ... usted podría considerar: No hacer esto en vim !!

Este es un ejemplo de uso clásico para lenguajes de scripting. Tome un tutorial básico de python, perl o ruby. La solución para esto sería estar en él.

La expresión regular para esto podría no ser demasiado difícil y es realizable en vim. Pero hay alternativas mucho más fáciles. Y mucho más flexibles.

1

¿Por qué vim?

probar este script de shell:

#!/bin/sh 

input=$1 

shipment=`grep Shipment $input|awk -F, '{print $2}'` 

mv $input $input.orig 

sed -e "s/^\([0-9]\)/$shipment,\1/" $input.orig > $input 

Se podría iterar a través de archivos específicos:

for input in *.txt 
do 
    script.sh $i 
done 
1

también creo que esto no es muy adecuado para vim, ¿qué hay en Bash en su lugar?

FILENAME='filename.csv' && SHIPMENT=`grep Shipment $FILENAME | sed 's/^Shipment,//'` && cat $FILENAME | sed "s/^[0-9]/$SHIPMENT,&/" > $FILENAME 
Cuestiones relacionadas