Как мне создать команду VIM или Vi для удаления всего текста после определенного символа для каждой строки в текстовом файле?

Сценарий:

  • У меня есть текстовый файл, в котором есть данные о строках (как в символе |).
  • Каждое поле данных в полях с ограничениями на канал может иметь переменную длину, поэтому счетные символы не будут работать (или использовать какую-либо функцию подстроки... если это даже существует в Vim).

Возможно ли, используя Vim/Vi, удалить все данные со второго канала в конец строки для всего файла? Есть около 150 000 строк, поэтому сделать это вручную будет только привлекательным для мазохиста...

например.

Измените следующие строки:

1111|random sized text 12345|more random data la la la|1111|abcde
2222|random sized text abcdefghijk|la la la la|2222|defgh
3333|random sized text|more random data|33333|ijklmnop

в

1111|random sized text 12345
2222|random sized text abcdefghijk
3333|random sized text

Я уверен, что это может быть сделано как-то... Надеюсь.

ТИА

ОБНОВЛЕНИЕ: Я должен был упомянуть, что я запускаю это в Windows XP, поэтому у меня нет доступа к некоторым из упомянутых команд * nix (CUT не распознается в Windows).

Ответы

Ответ 1

:%s/^\v([^|]+\|[^|]+)\|.*$/\1/

Ответ 2

Вы также можете записать макрос:

qq02f|Djq

а затем вы сможете воспроизвести его с помощью 100 @q, чтобы запустить макрос на следующих 100 строках.

Макро объяснение:

  • qq - запускает макросъемку
  • 0 - перейти к первому символу строки
  • 2f | - найти второе вхождение | символ на линии
  • D - удалите текст после текущей позиции до конца строки
  • j - перейти к следующей строке
  • q - завершает макросъемку

Ответ 3

Если вам не нужно использовать vim, другой альтернативой будет команда unix unix.

cut -d '|' -f 1-2 file > out.file

Ответ 4

Еще один способ сделать то же самое:

%s/^\(.\{-}|\)\{2}\zs.*//
%s/^\(.\{-}\zs|\)\{2}.*// " if you want to remove the 2nd pipe as well

На этот раз регулярное выражение соответствует как можно меньше (\ {-}) символов, за которыми следует труба, и дважды (\ {2}), они игнорируются (\z s), чтобы заменить все следующие (\ z s) текст ничем.

Ответ 5

Вместо подстановки можно использовать команду :normal для повторения последовательности двух команд Нормального режима, переходящих ко второму символу | и удалению все остальное до конца строки.

:%norm!2f|D

Ответ 6

Используйте команду: команда, с помощью которой вы можете легко выполнить команду пользователя.

:command -range=% YourNameHere <line1>,<line2>s/^\v([^|]+\|[^|]+)\|.*$/\1/

Ответ 7

Вы также можете сделать:

:%s/^\([^\|]\+|[^\|]\+\)\|.*$/\1/g

Ответ 8

использовать awk.

awk -F"|" '{$0=$1"|"$2}1' file

Ответ 9

Я обнаружил, что vim не очень подходит для обработки очень больших файлов. Я не уверен, насколько велик ваш файл. Может быть, кошка и семя будут работать лучше.

Ответ 10

Вот решение sed:

sed -e 's/^\([^|]*|[^|]*\).*$/\1/'

Ответ 11

Зачем использовать vim?

Почему бы просто не сделать

cat my_pipe_file | cut -d'|' -f1-2

Ответ 12

Это позволит отфильтровать все строки в буфере (1, $) через разрез, чтобы выполнить задание.

:1,$!cut -d '|' -f 1-2

Попробуйте

:.!cut -d '|' -f 1-2

Сделать это только в текущей строке.