2016-01-23 19 views
1

我有一个成绩单,看起来像这样加入特定的字线后,直到另一个特定的词

MICHEAL: blablablabla. 

further talk by Michael. 

more talk by Michael. 

VALERIE: blublublublu. 

Valerie talks more. 

MICHAEL: blibliblibli. 

Michael talks again. 

........ 

总而言之这种模式继续长达4000行,而不是仅通过两个扬声器但.txt文件最多可以有7个不同的扬声器,所有扬声器都带有以大写字母书写的独特名称(如上例所示)。 对于一些文本挖掘我需要重新安排该.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搜索:^是启动线,是一个大写字符,+意味着一个或多个匹配和是勿庸置疑:
  • 然后是棘手的位,我们使执行的命令的范围内,从匹配所以一些其他模式匹配。 /\ n \ u +:\ | \%$是由管道\ 。 \ n \ u +:是紧接着最后一个模式的新行,即下一位发言者之前的行。 \%$是文件的末尾
  • 加入做什么它在锡说

因此要将其放到一起:对于每一个扬声器,加入直到下一位发言者前行或结束文件。

的最接近分拣现在我是

:排序/ \ U +:/ R

这只会排序扬声器名和反向其他线路,所以它不是真的什么您正在寻找

+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

正则表达式:/([A-Z]+:)([A-Za-z\s\.]+)(?!\1)$/gm

说明:
([A-Z]+:)捕获仅包含大写字母的演讲嘉宾的名字。

([A-Za-z\s\.]+)捕获对话。

(?!\1)$对发言者姓名的反向引用,并比较下一个发言者是否与最后一个发言者相同。如果不是,则匹配直到找到新的扬声器。

我希望这会帮助您至少匹配。

0

以下是针对您的问题的脚本解决方案。

它没有很好的测试,所以我添加了一些评论,所以你可以很容易地修复它。

,使其运行,只是:

  • 填补g:speakers VAR在您需要的大写名称脚本的顶部;
  • 来源脚本(例如::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 
相关问题