2016-11-01 16 views
2

Мне нужно сделать это упражнение о регулярных выражениях и манипуляциях с текстом в vim.vim: заменить конкретный символ, но только после n-го события

Так что у меня этот файл о самых скоринг футболистов в истории, с 50 записей вида:

1 Cristiano Ronaldo Portugal 88 121 0.73 03 Manchester United Real Madrid

В пробелы между полями вкладки (\ т)

поля каждый реагирует на другую категорию: и т. д. Это последнее поле содержит один или несколько клубов, в которые игрок играл. (так не фиксированное количество клубов)

Вопрос: re поместите все вкладки с символом ';', за исключением последнего поля, где клубы должны быть разделены символом ','.

Поэтому я подумал: я просто заменю их запятой, а затем заменим первые 7 запятых точкой с запятой. Но как вы это делаете? Разрешено все - от регулярных выражений до команд vim.

Первая часть проста: :2,$s/\t/,/g Но вторая часть, я не могу понять.

Любая помощь была бы принята с благодарностью.

Спасибо, Зенон

+0

ли это быть решение регулярных выражений, или бы использовать некоторую комбинацию других функций VIM (глобальные команды, обычные команды, макросы и т.д.) будет в порядке? – DJMcMayhem

+0

Да, команды разрешены, я просто «предположил», что это будет сделано с регулярным выражением, я соответственно изменю заголовок –

ответ

2

Этот ответ похож на @ Amadan, но он использует способность обеспечить выражение, как заменить строку на самом деле сделать трудный немного изменить первый набор вкладок с запятой:

%s/\v(.{-}\t){7}/\=substitute(submatch('0'), '\t', ';', 'g')/|%s/\t/,/g 

Разбитое это набор из трех команд замены. Первые два мощеных вместе с sub-replace-expression:

%s/\v(.{-}\t){7}/\=substitute(submatch('0'), '\t', ';', 'g')/ 

Что это делает найти именно семь occurrances ({7}) любого характера, за которым следует вкладке, в не жадный способом. ((.{-}\t)). Затем мы заменим все это совпадение (submatch(0)) с результатом выражения-заменителя (\=substitute(...)). Подставляемое выражение просто для сравнения, поскольку оно просто преобразует все вкладки в точки с запятой.

Последний подменю просто изменяет любые другие вкладки на линии запятыми.

См :help sub-replace-expression

+0

Кажется, что это сработает! Только один вопрос: правильно ли я должен быть астерикс после точки? –

+0

№. '*' Будет жадным совпадением и будет потреблять все до последней вкладки. '{-}' - не жадная версия. В этом случае это не имеет особого значения из-за '{7}', но в целом я считаю, что лучше использовать не-жадный матч, если вы действительно не хотите жадного. –

+0

О, ладно спасибо! Примите этот ответ вместо моего, потому что я думаю, что он лучше масштабируется, чем мое решение. –

0

Вот один из способов вы можете сделать это:

:let @q=":s/\t/;\<cr>" 
:2,$norm [email protected] 
:2,$s/\t/,/g 

Объяснение:

Во-первых, мы определим макрос 'Q', который заменит один вкладку с точка с запятой. Теперь на любой строке мы можем просто запустить этот макрос n раз, чтобы заменить первые n вкладки. Для того, чтобы делать это автоматически для каждой строки, мы используем norm команду:

:2,$norm [email protected] 

Это, по существу, то же самое, буквально печатая [email protected] (например, «запустить макрос„Q“семь раз») на каждой строке в указанном диапазоне , Оттуда мы можем просто заменить каждую вкладку запятой.

:2,$s/\t/,/g 
+1

Кроме того, вы знаете, есть также [выделенный сайт vim] (http: //vi.stackexchange .com), о которых вы могли бы задать свои вопросы в будущем. – DJMcMayhem

+0

кажется твердым откликом, я немедленно проверю его. Для чего используется '\ '? –

+0

'' \ "' - это то, как вы описываете возврат буквальной каретки. Ввод его таким образом важен, так что команда substitute фактически запускается. В противном случае вы получите нечто вроде 's/\ t/;: s/\ t/;: s/\ t/;: s/\ t/;: s/\ t/;: s/\ t/;: s/\ t /; 'и vim ждет вас, чтобы нажать enter. – DJMcMayhem

0
:2,$s/\t\(.*\t\)\@=/;/g 
:2,$s/\t/, 
  • Изменить любые вкладки, где Существует вкладка позже ;
  • Изменить оставшиеся вкладки в ,

EDIT: неправильное понимание.Вот фиксированная версия:

:2,$s/\(\(\t.*\)\{7}\)\@<=\t/,/g 
:2,$s/\t/;/g 
  • Изменить любые вкладки, где есть семь вкладок перед ним, чтобы ,
  • Изменить оставшиеся вкладки в ;
+0

Как я вижу ваш ответ, последняя вкладка заменяется запятой. Однако не каждая строка одинакова, поэтому у игрока может быть один клуб: тогда ему не нужна запятая, или у игрока могут быть 3 клуба, а затем ему нужны две запятые –

0

Мой PatternsOnText plugin имеет (среди прочих) :SubstituteSelected команда, которая позволяет указать позиции соответствия. При этом, вы можете легко заменить первые 8 вкладок с запятой, а затем использовать обычную замену, чтобы изменить остальные вкладки в запятых:

:2,$SubstituteSelected/\t/;/g 1-8 
:2,$s/\t/,/g 
+0

да, я видел ваш (или другие) плагин , но я предпочел бы сделать это без плагинов, так как решение должно быть воспроизведено учителем. Я нашел ответ, хотя, отвечу сам. Спасибо за ответ! –

0

Мы решили проблему, просто захватив первые 8 групп вручную ([^\t]*\t)(...)(...), а затем отделите их точкой с запятой (\1;\2;...;), затем замените оставшиеся табы запятой | 2,$s/\t/,/g

Спасибо всем, кто пытается помочь!