Regex 将特定单词后的行连接到另一个特定单词
我有一个.txt文件的成绩单,看起来像这样Regex 将特定单词后的行连接到另一个特定单词,regex,join,vim,Regex,Join,Vim,我有一个.txt文件的成绩单,看起来像这样 MICHEAL: blablablabla. further talk by Michael. more talk by Michael. VALERIE: blublublublu. Valerie talks more. MICHAEL: blibliblibli. Michael talks again. ........ 总而言之,这种模式最多可使用4000行,不只是两个扬声器,而是多达七个不同的扬声器,所有扬声器都具有用大写字
MICHEAL: blablablabla.
further talk by Michael.
more talk by Michael.
VALERIE: blublublublu.
Valerie talks more.
MICHAEL: blibliblibli.
Michael talks again.
........
总而言之,这种模式最多可使用4000行,不只是两个扬声器,而是多达七个不同的扬声器,所有扬声器都具有用大写字母书写的唯一名称(如上面的示例所示)。
对于一些文本挖掘,我需要按照以下方式重新排列这个.txt文件
MICHAEL: blablablabla. further talk by Michael. more talk by Michael.
VALERIE: blublublublu. Valerie talks more.
MICHAEL: blibliblibli. Michael talks again.
任何帮助都会被极大地吸引 在vim中,您可以采取两步方法,首先替换所有换行符
:%s/\n\+/ /g
然后在术语大写:
前插入新行,第一行除外:
:%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>
:nnoremap:%s/\n\+//g\\\\%s/\([[:upper:]\+:\)/\r\1/g\\\\\\\%sort!
如果在正常模式下按F5,则会发生转换。请注意,
|
需要在nnoremap
命令中进行转义。我对vim
了解不多,但我正要匹配与特定扬声器对应的行,下面是实现这一点的方法正则表达式:
/([A-Z]+:)([A-Za-Z\s\.]+)(?!\1)$/gm
说明:
([A-Z]+:)
捕获只包含大写字母的说话人姓名([A-Za-z\s\.]+)
捕获对话。(?!\1)$
反向引用演讲者的姓名,并比较下一个演讲者是否与上一个演讲者相同。如果不匹配,则匹配直到找到新的扬声器
我希望这至少能帮助您进行匹配。好的,首先回答:
:g/^\u\+:/,/\n\u\+:\|\%$/join
现在解释一下:
- g代表全局,并在匹配的每一行上执行以下命令
- /^\u+:/是模式:g搜索:^是行的开头,\u是大写字符,+表示一个或多个匹配项,:是:
- 然后是棘手的一点,我们将执行的命令设置为一个范围,从匹配到其他模式匹配/\n\u+:\\\%$是由管道分隔的两部分\n\u+:是一个新行,后跟最后一个模式,即下一个发言者前面的行\%%$是文件的结尾
- join照罐头上写的做
这将只按说话人姓名排序,并反转另一行,因此它不是您真正想要的以下是解决您问题的脚本解决方案 它没有经过很好的测试,所以我添加了一些注释,以便您可以轻松地修复它 要使其运行,只需执行以下操作:
- 在脚本顶部的
var中填入所需的大写名称李>g:speakers
- 脚本的源代码(例如:sav/tmp/script.vim | so%)李>
- 运行
通过扬声器连接线路李>:调用JoinAllSpeakLines()
- 运行
进行排序:调用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
“用所有扬声器名称填充以下数组:
让g:演讲者=[‘迈克尔’、‘瓦莱丽’、‘马修’]
呼叫排序(g:扬声器)
函数!JoinAllSpeakLines()
在整个文件中,将两个大写扬声器名称之间的所有行连接起来
后跟“:”,第一个包含:
静默g/\u\{2,}:/call JoinSpeakLines
endf
函数!SortSpeakLines()
“按发言人对整个文件进行排序,保持
“每位发言者。
“必须在JoinAllSpeakLines()之后调用。
“创建一个新的dict,每个扬声器一个键:
设speakerlines={}
对于g中的演讲者:演讲者
让speakerlines[扬声器]=[]
外循环
“对于文件中的每一行:
对于getline中的行(1,“$”)
let speaker=GetSpeaker(行)
如果演讲者=“”
持续
恩迪夫
“将该行添加到右侧扬声器:
呼叫添加(speakerlines[扬声器],线路)
外循环
“删除当前缓冲区中的所有内容:
正常gg“_dG
“添加已排序的行,每个发言者:
对于g中的演讲者:演讲者
调用附加(行(“$”),speakerlines[speaker])
外循环
“删除缓冲区中的第一行(空):
正常gg“\u dd
endf
功能!GetOtherSpeakerPattern(扬声器)
“返回一个模式,该模式匹配除
“一个参数。
“创建一个新列表,删除:演讲者:
让他人=复制(g:发言者)
设idx=索引(其他,a:扬声器)
如果idx!=-1
呼叫删除(其他,idx)
恩迪夫
创建并返回模式列表,如下所示
“这个:“\v |…”
调用映射(其他,'printf(“:”,v:val)'
返回“\v”。加入(其他“|”)
endf
函数!获取扬声器(线路)
返回一行中后跟“:”的大写名称
返回matchstr(a:line'\u\{2,}\ze:')
endf
功能!JoinSpeakLines_uuu()
当光标位于带有大写名称的行上时,将所有
“以下几行