vim & csv file: поместите информацию заголовка в новый столбец - PullRequest
5 голосов
/ 15 мая 2009

У меня есть большое количество CSV-файлов, которые выглядят следующим образом:


XXXXXXXX
ххххх
Пересылка, YD564n
XXXXXXXXX
ххххх

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


Мне нужно, чтобы они выглядели следующим образом:


XXXXXXXX
ххххх
Пересылка, YD564n
XXXXXXXXX
ххххх

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


YD564n является номером отгрузки и будет отличаться для каждого файла CSV. Но это всегда приходит сразу после «Отгрузки».

Какие команды vim я могу использовать?

Ответы [ 6 ]

4 голосов
/ 15 мая 2009

В одном файле введите следующее в обычном режиме:

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

Обратите внимание, что <CR> - это клавиша ENTER, а <C-R> - это CTRL-R.

Это обновит этот файл и запишет команды в регистр q.

Затем в каждом другом файле типа @q (также в обычном режиме). (будет воспроизведен регистр q)

3 голосов
/ 15 мая 2009

Вы можете сделать это с помощью макроса и применить его к нескольким файлам.

Вот один пример. Введите следующее как есть:

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

Теперь это выглядит ужасно. Дайте мне посмотреть, смогу ли я объяснить это немного лучше.

3gg$: перейти к концу третьей строки.

"ayiw: скопировать последнее слово в регистр a.

:6,$s/^/<C-R>a/<CR>: В каждой строке начиная с 6-го числа в начале заменить все, что есть в регистре a.

:w<CR>:bn<CR>: сохранить и перейти к следующему буферу.

Теперь вы можете сопоставить это с ключом,

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

Тогда, если у вас, скажем, 200 CSV-файлов, вы открываете vim как

vim *.csv

, а затем

200<C-A>

Там, где вы набираете Ctrl-A, и все должно быть сделано.

Тем не менее, мне определенно было бы удобнее делать это на надлежащем языке сценариев, это было бы намного проще.

2 голосов
/ 15 мая 2009

Это можно сделать как однострочник Perl:

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

Это будет считывать содержимое shipment.csv в $c, извлекать идентификатор отправки в $n и добавлять в каждую строку CSV номер отправки. Файл будет изменен на месте с сохранением резервной копии в shipment.csv.bak.

Чтобы сделать это из Vim, адаптируйте его как фильтр:

:%!perl -e' $c = do {local $/; <>}; ($n) = ($c =~ /Shipment,(\w+)/); $c =~ s/^(\d+,)/$n,$1/gm; print $c'
1 голос
/ 15 мая 2009

Я также думаю, что это не очень подходит для vim, а как насчет Bash?

FILENAME='filename.csv' && SHIPMENT=`grep Shipment $FILENAME | sed 's/^Shipment,//'` && cat $FILENAME | sed "s/^[0-9]/$SHIPMENT,&/" > $FILENAME
1 голос
/ 15 мая 2009

Почему VIM?

Попробуйте этот сценарий оболочки:

#!/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

Вы можете перебирать определенные файлы:

for input in *.txt
do
    script.sh $i
done
1 голос
/ 15 мая 2009

Ну, не ругайте меня, но ... вы можете подумать: не делайте этого в vim !!

Это классический пример использования языков сценариев. Возьмите базовый учебник по Python, Perl или Ruby. Решение для этого будет быть в этом.

Регулярное выражение для этого может быть не слишком сложным, и выполнимо в vim. Но есть гораздо более простые альтернативы. И гораздо более гибкие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...