2014-09-24 2 views
4

Рассмотрят следующие данные:Заменить группы текста вместе с GVim

Class Gender Condition Tenis 
A Male Fail Fail 33 
A Female Fail NotFail 23 
S Male  Yellow  14 
BC Male Happy Elephant 44 

У меня есть запятая значение с бесформатным табулировании (она варьирует среди вкладок и пробелов).

В одном конкретном столбце у меня есть составные слова, которые я хотел бы исключить. В приведенном выше примере я хотел бы заменить «Fail» «Fail_» и «Happy» на «Happy_».

Результат будет следующим:

Class Gender Condition Tenis 
A Male Fail_Fail 33 
A Female Fail_NotFail 23 
S Male  Yellow  14 
BC Male Happy_Elephant 44 

я уже успел сделать это в два этапа:

:%s/Fail /Fail_/g 
:%s/Happy /Happy_/g 

Вопрос: Как я новичок в GVim Я пытаюсь для реализации этих замен все вместе, но я не мог найти, как это сделать *.

После этого шага, я пластинчатый мои данные следующим:

:%s/\s\+/,/g 

И получить окончательный результат:

Number,Gender,Condition,Tenis 
A,Male,Fail_Fail,33 
A,Female,Fail_NotFail,23 
S,Male,Yellow,14 
BC,Male,Happy_Elephant,44 

На SO, я искал [vim] :%s two is:question и некоторые вариации, но Я не мог найти связанный поток, поэтому, я думаю, мне не хватает правильной терминологии.


Edit: Это фактические данные (с более чем 1 миллиона строк). Проблема начинается в 12-й колонке (например, «Fail Planting» должна быть «Fail_Planting»).

SP1  51F001  3 1 1 2 3 2001 52 52 H Normal   17,20000076 23,39999962 NULL NULL 
SP1  51F001  3 1 1 2 3 2001 53 53 F Fail Planting 0 0 NULL NULL 
SP1  51F001  3 1 1 2 3 2001 54 54 N Normal   13,89999962 0 NULL NULL 
+0

Безопасно предположить, третье слово в строке всегда будет требовать подчеркивания или есть какая-либо строка, которые не соответствуют этому требованию? –

+0

Хммм, основываясь на этих данных, похоже, что вы не всегда хотите добавить символ подчеркивания (потому что в столбце также содержатся значения одного слова). Это делает мой макрос ответом безрезультатно =/ –

+0

Я думаю, вам не повезло сделать это из командной строки vim. У вас есть доступ к языку сценариев или языку программирования (это не слишком сложно для чего-то вроде C#). –

ответ

7

Вы можете использовать выражение в правой части подстановки.

:%s/\(Fail\|Happy\) \|\s\+/\= submatch(0) =~# '^\s\+$' ? ',' : submatch(1).'_'/g 

Так это находит Fail или Happy или пропуски, а затем преобразует проверки, чтобы увидеть, если соответствует части полностью пробельные. Он заменяется запятой, если он не использует захваченную часть и добавляет символ подчеркивания. submatch(0) - это весь матч, и submatch(1) - первая группа захвата.

Посмотрите на :h sub-replace-expression. Если вы хотите сделать что-то очень сложное, вы можете определить функцию.


Очень волшебная версия

:%s/\v(Fail|Happy) |\s+/\= submatch(0) =~# '^\v\s+$' ? ',' : submatch(1).'_'/g 
5

Вы могли бы, возможно, попробовать макрос, если есть определенные условия, которые истинны (или написать vimscript, но мой vimscript очень ржавый).Я покажу пример макроса вы можете использовать:

  • Перейти к первой строке в файле после заголовка
  • пресс д, чтобы начать запись макроса
  • пресс т выбрать регистр t для запись на (я использую т для «темп»)
  • пресс ^, чтобы перейти к началу строки
  • пресс ж, чтобы перейти к третьему слову (переместить 2 слова справа)
  • нажмите е, чтобы перейти к концу слова
  • пресс л (буква л), чтобы переместить правильный символ (в пространстве)
  • пресс-г ввести замены одного символа режима
  • пресса _ ввести символ подчеркивания
  • пресс J двигаться вниз линию
  • пресс д, чтобы остановить запись макроса

Теперь, когда у вас есть макрос, хранящийся в регистре t вы можете запустить макрос на каждой строке в файле. Если есть 100 строк в файле, вы уже сделали 1 и есть заголовок, так что вы должны ввести следующее, чтобы запустить его на оставшиеся 98 линий:

  • @t
+1

Нет проблем. Вы даже можете хранить макросы в своем файле vimrc, если у вас есть тот, который вы часто используете. Что касается тройных составных слов, макрос не будет работать, потому что он просто повторяет те же действия, которые вы записали (которые передавали только двойное составное слово). Если вы не можете запускать команду в каждой строке, которая могла бы обрабатывать обе ситуации (не уверен, что макрос запишет в командной строке тоже ... что-то, на что я должен обратить внимание!). –

+0

Хорошо, сделано @AndreSilva –

6

У вас есть все части, нужно просто объединить их вместе с |.Пример:

:%s/\>\s\</_/g|%s/\s\+/,/g 

Я использую \> и \<, чтобы найти слова, которые имеют только одно пространство между ними таким образом, мы можем заменить его _.

Для получения дополнительной справки обратитесь к разделу:

:h /\> 
:h :range 
:h :bar 
+0

Большая проблема заключается в том, что вы перегружаете пространство как разделитель, так и нормальное пространство внутри поля. Возможно, вы можете настроить свою первую подстановку так: 's% \ \ w \ zs \ s \ ze \ w/_ /'. Примечание. Вероятно, это будет процесс проб и ошибок. –

+0

Теперь, наконец, я получил ваш ответ и оператор (лучше поздно, чем никогда). Я использовал ':% s/Fail/Fail_/g |% s/Happy/Happy_/g', и это сработало. Спасибо (+1). –

2

Эти две команды:

:%s/\(\a\) \(\a\)/\1_\2/g 
:%s/\s\+/,/g 

, кажется, работает на образец:

SP1,51F001,3,1,1,2,3,2001,52,52,H,Normal,17,20000076,23,39999962,NULL,NULL 
SP1,51F001,3,1,1,2,3,2001,53,53,F,Fail_Planting,0,0,NULL,NULL 
SP1,51F001,3,1,1,2,3,2001,54,54,N,Normal,13,89999962,0,NULL,NULL 

, но у вас есть десятичные числа здесь с запятой как разделитель, который будет конфликтовать с данными, разделенными запятыми. Изменение этих запятых в периоды заранее может быть хорошей идеей:

:%s/,/./g 

SP1,51F001,3,1,1,2,3,2001,52,52,H,Normal,17.20000076,23.39999962,NULL,NULL 
SP1,51F001,3,1,1,2,3,2001,53,53,F,Fail_Planting,0,0,NULL,NULL 
SP1,51F001,3,1,1,2,3,2001,54,54,N,Normal,13.89999962,0,NULL,NULL 
+1

'\ (foo \)' - группа захвата, которую вы повторно используете в замещающей части с '\ n':' \ 1' для первой группы, '\ 2' для второго ... regex предназначен только для' letterpaceletter 'и, вероятно, необходимо будет изменить, чтобы удовлетворить все ваши требования. – romainl

Смежные вопросы