Макрос VIM: специальная сортировка: как? - PullRequest
3 голосов
/ 30 января 2012

Вот список, который у меня есть:

Word1
Word2
...
Word4 / Word5 Word6
Word7
Word8 Word9 Word10 / Word11 Word12 Word13 Word14
Word15
Word16
...

А вот что я хотел бы иметь:

Word1
Word2
...
Word4 Word6
Word5 Word6
Word7
Word8 Word9 Word10 Word14
Word11 Word12 Word13 Word14
Word15
Word16
...

т.е. иногда есть косая черта / между группой из 1, 2 или 3 слов (назовем их g1 и g2), а после этих "групп" есть еще несколько слов (назовем их g3) , Я хотел бы разбить эту строку на две строки, например: строка 1 = g1 g3 и строка 2 = g2 g3

Не могли бы вы сделать это в одном макросе или объяснить мне, как это сделать?

Ответы [ 3 ]

2 голосов
/ 30 января 2012

Вы можете написать function в expand slash:

fun! ExpandSlash() range
    for i in range(a:firstline, a:lastline)
        let ws = split(getline(i))
        let idx = index(ws, '/')
        if idx==-1
            continue
        endif
        let h= join(ws[ : idx-1])
        let m= join(ws[idx+1 : 2*idx])
        let t= join(ws[2*idx+1 : ])
        call setline(i, h.' '.t.'/'.m.' '.t)
    endfor
endfun

:%call ExpandSlash()
:%s@/@\r@

до

1 2 3 / 4 5 6 7 8

после

1 2 3 7 8
4 5 6 7 8
2 голосов
/ 31 января 2012

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

:g~/~s~\s*/\s*~\r~|-|exe's/\ze\n\%(\s*\w\+\)\{'.len(split(getline('.'))).'}\(.*\)$/\1'

Эта команда :global выбирает линии, соответствующие шаблону / (здесь это окружен ~ символами) и выполняет команды, которые идут после него для каждая из этих строк. Давайте рассмотрим их по одному.

  1. Символ косой черты с необязательным окружающим пробелом, который разделяет первую и вторую группы слов на текущей строке (с точки зрения постановки вопроса), заменяется новой строкой символ,

    :s~\s*/\s*~\r~
    

    Здесь символы тильды снова используются для разделения шаблона и замещающая строка, так что нет необходимости экранировать от косой черты.

  2. После замены курсор находится на строке рядом с тот, где / был. Для удобства формулировки следующих команд, курсор перемещается на одну строку вверх,

    :-
    

    - - это сокращение для диапазона .-1, обозначающее линию предшествующий текущему (см. :help :range).

  3. Третья группа слов, которая сейчас находится в конце следующей строки, быть добавленным к текущему. Чтобы сделать это, количество слова в первой группе определяется. С текущей строки содержит только первую группу, это число рассчитывается по разделение содержимого строки на группы, разделенные пробелами используя функцию split(),

    len(split(getline('.')))
    

    (getline('.') вернуть текущую строку в виде строки, split() преобразует эту строку в список слов, len() считает число элементов в списке.)

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

    :exe's/\ze\n\%(\s*\w\+\)\{'.len(split(getline('.'))).'}\(.*\)$/\1'
    

    Замены имеют следующую структуру,

    :s/\ze\n\%(\s*\w\+\)\{N}\(.*\)$/\1

    где N - количество слов, которые были помещены перед слэш.

    Шаблон соответствует символу новой строки текущей строки точно на N слов во второй строке. Слово соответствует последовательность пробелов, предшествующих серии из одного или нескольких слов символы (см. :help /\s и :help /\w). Шаблон слова заключенные в скобки \%( и \) (см. :help /\%() для обработки его как отдельного атома для спецификатора \{N} (см. :help /\{), чтобы точно соответствовать N вхождений этого. оставшийся текст до конца следующей строки сопоставляется как подгруппа ссылка на строку подстановки.

    Из-за атома \ze в самом начале шаблона его совпадение имеет нулевую ширину (см. :help /\ze). Итак, замена заменяет эту пустую строку перед символом новой строки на текст соответствует подгруппе, вставляя третью группу слов после первый.

0 голосов
/ 30 января 2012

Для данного примера результат эквивалентен замене каждого / последним словом в строке и переводом строки \r. Вот глобальная замена команды, чтобы сделать это:

:%s#/ \ze.*\(\<\w\+$\)#\1\r#

Пояснение:

  • / \ze соответствует / совпадению конечной остановки (ничего после \ze не будет подставлено)
  • .* соответствует любым промежуточным символам
  • \( начать другую группу матчей
  • \<\w\+$ соответствует последнему слову перед концом строки
  • \) остановить группу совпадений

Однако затем вы говорите, что конечная группа g3 может содержать более одного слова, что означает, что операция замены должна иметь возможность подсчитывать количество слов до и после /. Боюсь, я не знаю, как это сделать, но я уверен, что кто-то скоро прыгнет вам на помощь!

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