2016-01-23 3 views
1

У меня есть .txt файл транскрипт, который выглядит как этотРегистрация строки после определенного слова до другого конкретного слова

MICHEAL: blablablabla. 

further talk by Michael. 

more talk by Michael. 

VALERIE: blublublublu. 

Valerie talks more. 

MICHAEL: blibliblibli. 

Michael talks again. 

........ 

Всего в этой модели продолжается до 4000 линий, а не только двух динамиков, но с до семи разных динамиков, все с уникальными именами, написанными с прописными буквами (как в примере выше). Для некоторых текстовых добычи полезных ископаемых мне нужно изменить этот файл .txt следующим образом

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

    MICHAEL: blablablabla. further talk by Michael. more talk by Michael. 
    
    VALERIE: blublublublu. Valerie talks more. 
    
    MICHAEL: blibliblibli. Michael talks again. 
    
  2. Отсортировать теперь правильно соединенные строки в файле .txt в алфавитном порядке, так что все линии, произнесенные динамик теперь вместе. Но функция сортировки не должна сортировать предложения, произнесенные одним оратором (после сортировки каждой колонки).

Я знаю некоторые основные команды vim, но этого недостаточно, чтобы понять это. Особенно, первый. Я не знаю, какой шаблон я могу реализовать в vim, чтобы он только соединял строки каждого динамика.

Любая помощь была бы очень apperciated!

ответ

3

Хорошо, первый ответ:

:g/^\u\+:/,/\n\u\+:\|\%$/join 

И теперь объяснение:

  • г означает глобальный и выполняет следующую команду на каждой строке, которая соответствует
  • /^ \ u +:/ - это шаблон : g ищет :^ является начало строки, \ U является верхним регистром символов, + означает один или несколько матчей и : неудивительно:
  • затем приходит хитрые немного, мы делаем введённую команду диапазона, от так что некоторые другие шаблоны совпадают. /\ n \ u +: \ | \% $ состоит из двух частей, разделенных трубой \ | , \ n \ u +: - это новая строка, за которой следует последний шаблон, т. е. строка перед следующим динамиком. \% $ конец файла
  • присоединиться делает то, что он говорит на олове

Так, чтобы положить его вместе: Для каждого громкоговорителя, присоединитесь до линии до следующего оратора или в конце файл.

Ближайший к перебору я теперь является

: сортировка/\ и +:/г

, который будет только сортировать по имени динамиком и реверс другой линии, так что на самом деле не что вы ищете

+0

Спасибо ваше для этого кода и объяснения. Команда соединения работала очень хорошо. –

0

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

:%s/\n\+/ /g 

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

:%s/ \([[:upper:]]\+:\)/\r\1/g 

Для сортировки вы можете использовать программу UNIX сортировки:

:%sort! 

Вы можете объединить их с использованием символа трубы:

:%s/\n\+/ /g | %s/ \([[:upper:]]\+:\)/\r\1/g | %!sort 

и сопоставить их на ключ в файле vimrc:

:nnoremap <F5> :%s/\n\+/ /g \| %s/ \([[:upper:]]\+:\)/\r\1/g \| %sort! <CR> 

Если нажать F5 в обычном режиме, преобразование происходит. Обратите внимание, что | должен быть экранирован в команде nnoremap.

0

Ну, я не знаю много о vim, но я собирался сопоставить строки, соответствующие конкретному динамику, и вот для этого regex.

Regex:/([A-Z]+:)([A-Za-z\s\.]+)(?!\1)$/gm

Объяснение:
([A-Z]+:) захватывает имя говорящего, который содержит только заглавные буквы.

([A-Za-z\s\.]+) отражает диалог.

(?!\1)$ обратная ссылка на имя спикера и сравнивает, если следующий динамик был таким же, как и последний. Если нет, то оно будет соответствовать, пока не будет найден новый динамик.

Я надеюсь, что это поможет вам с совпадением, по крайней мере.

0

Это решение для вашей проблемы.

Это не очень хорошо протестировано, поэтому я добавил несколько комментариев, чтобы вы могли легко его исправить.

Для того, чтобы запустить его, просто:

  • заполнить g:speakers вар в верхней части сценария с прописных именами, вам нужно;
  • источник сценария (например: :sav /tmp/script.vim|so %);
  • запустить :call JoinAllSpeakLines(), чтобы присоединиться к линиям с помощью динамиков;
  • пробег :call SortSpeakLines() сортировать

Вы можете адаптировать различные модели, чтобы лучше соответствовать вашим потребностям, например, добавив некоторое пространство толерантности (\u\{2,}\s*\ze:).

Вот код:

" Fill the following array with all the speakers names: 
let g:speakers = [ 'MICHAEL', 'VALERIE', 'MATHIEU' ] 
call sort(g:speakers) 


function! JoinAllSpeakLines() 
" In the whole file, join all the lines between two uppercase speaker names 
" followed by ':', first inclusive: 
    silent g/\u\{2,}:/call JoinSpeakLines__() 
endf 

function! SortSpeakLines() 
" Sort the whole file by speaker, keeping the order for 
" each speaker. 
" Must be called after JoinAllSpeakLines(). 

    " Create a new dict, with one key for each speaker: 
    let speakerlines = {} 
    for speaker in g:speakers 
     let speakerlines[speaker] = [] 
    endfor 

    " For each line in the file: 
    for line in getline(1,'$') 
     let speaker = GetSpeaker__(line) 
     if speaker == '' 
      continue 
     endif 
     " Add the line to the right speaker: 
     call add(speakerlines[speaker], line) 
    endfor 

    " Delete everything in the current buffer: 
    normal gg"_dG 

    " Add the sorted lines, speaker by speaker: 
    for speaker in g:speakers 
     call append(line('$'), speakerlines[speaker]) 
    endfor 

    " Delete the first (empty) line in the buffer: 
    normal gg"_dd 
endf 

function! GetOtherSpeakerPattern__(speaker) 
" Returns a pattern which matches all speaker names, except the 
" one given as a parameter. 
    " Create an new list with a:speaker removed: 
    let others = copy(g:speakers) 
    let idx = index(others, a:speaker) 
    if idx != -1 
     call remove(others, idx) 
    endif 
    " Create and return the pattern list, which looks like 
    " this : "\v<MICHAEL>|<VALERIE>..." 
    call map(others, 'printf("<%s>:",v:val)') 
    return '\v' . join(others, '|') 
endf 

function! GetSpeaker__(line) 
" Returns the uppercase name followed by a ':' in a line 
    return matchstr(a:line, '\u\{2,}\ze:') 
endf 

function! JoinSpeakLines__() 
" When cursor is on a line with an uppercase name, join all the 
" following lines until another uppercase name. 
    let speaker = GetSpeaker__(getline('.')) 
    if speaker == '' 
     return 
    endif 
    normal V 
    " Search for other names after the cursor line: 
    let srch = search(GetOtherSpeakerPattern__(speaker), 'W') 
    echo srch 
    if srch == 0 
     " For the last one only: 
     normal GJ 
    else 
     normal kJ 
    endif 
endf 
Смежные вопросы