在Vim中执行条件行拆分的复杂情况
以下是我正在处理的文本示例:在Vim中执行条件行拆分的复杂情况,vim,Vim,以下是我正在处理的文本示例: Word1 Word2 ... Word4 / Word5 Word6 Word7 Word8 Word9 Word10 / Word11 Word12 Word13 Word14 Word15 Word16 ... 我想通过拆分包含 斜杠分隔块,以便第一个块(斜杠前面) 获取从第二个块(位于 斜线)使两行中的字数相等,由 如果前一个词比后一个词少的话 换句话说,所需的转换是以线条为目标 由两组单词组成,两组单词之间用空格隔开(包围) 斜杠字符。上的第一组单词(斜
Word1
Word2
...
Word4 / Word5 Word6
Word7
Word8 Word9 Word10 / Word11 Word12 Word13 Word14
Word15
Word16
...
我想通过拆分包含
斜杠分隔块,以便第一个块(斜杠前面)
获取从第二个块(位于
斜线)使两行中的字数相等,由
如果前一个词比后一个词少的话
换句话说,所需的转换是以线条为目标
由两组单词组成,两组单词之间用空格隔开(包围)
斜杠字符。上的第一组单词(斜杠前)
目标行有1到3个单词,但总是少于第二个单词
小组
因此,目标线具有以下结构:
嫀G1›/
èG2›èG3›
其中èG1›和
嫀G2›èG3›(即。,
嫀G2›与èG3›连接)
构成上述两组单词,用
嫀G2›代表本书中的许多主要词语
后斜杠组与前斜杠组相同,以及
èG3›代表表格中的剩余单词
后斜杠组
此类线路应替换为两条线路,如下所示:
Word1
Word2
...
Word4 Word6
Word5 Word6
Word7
Word8 Word9 Word10 Word14
Word11 Word12 Word13 Word14
Word15
Word16
...
嫀G1›èG3›嫀G2›èG3› 对于上述示例,预期结果如下所示:
Word1
Word2
...
Word4 Word6
Word5 Word6
Word7
Word8 Word9 Word10 Word14
Word11 Word12 Word13 Word14
Word15
Word16
...
您能帮我在Vim中实现这个转换吗?对于给定的示例,结果相当于用行上的最后一个单词和换行符替换每个
/
。下面是执行此操作的全局替换命令:
:%s#/ \ze.*\(\<\w\+$\)#\1\r#
:%s#/\ze.*\(\您可以编写一个函数
到展开斜杠
:
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
之前
之后
可以使用以下命令执行所需的转换:
:g~/~s~\s*/\s*~\r~|-|exe's/\ze\n\%(\s*\w\+\)\{'.len(split(getline('.'))).'}\(.*\)$/\1'
此:global
命令选择与模式匹配的行/
(这里,它由~
字符分隔)并执行命令
每一行都是这样
让我们逐一考虑。
包含可选周围空白的斜杠字符
分隔表上的第一组和第二组单词
当前行(如问题陈述中所定义)为
替换为换行符:
:s~\s*/\s*~\r~
这里再次使用波浪线字符来分隔波浪线
模式和替换字符串,这样就没有
我们需要逃离刀口
在上述替换之后,光标位于行上
在被替换的斜杠旁边。用来书写
以下命令更方便,光标向后移动
就在上面的那一行:
:-
-
地址是-1
范围的缩写,表示
当前行之前的行(请参见:help:range
)
第三组单词,现在位于下一组单词的末尾
行,将被追加到当前行。为了
即,确定第一组中的字数。
由于当前行仅包含第一个组,因此
数字可以通过分隔该文件的内容来计算
在
split()
函数:
len(split(getline('.')))
getline('.')
调用以字符串形式返回当前行,
split()
将该字符串转换为单词列表,然后
len()
统计该列表中的项目数
使用字数生成替换命令
并使用:执行命令运行:
: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
)。谢谢
为此,替换命令将替换空字符串
在换行符前面,文本与
子组,从而在
第一个
太谢谢你了,我明天就来试试。你帮了我很多你想象不到的事。几个小时的手工“分类”已经过去了!太谢谢你了!谢谢你的回答,我会尽力理解的…等我有时间的时候time@OlivierPons:从某种意义上说,它是。:-)明天我将添加详细的解释。好主意,可以帮助像我这样的初学者=)@OlivierPons:我已经添加了对建议命令的解释。非常感谢这可能对社区(包括我!)有帮助。您忘记了组g1
和g2
可能包含多个单词(但单词数始终相同)我认为我的命令可以处理g1
和g2
中的多个单词。它所做的只是用最后一个单词替换/
,因此g1
和的精确组合
len(split(getline('.')))
:exe's/\ze\n\%(\s*\w\+\)\{'.len(split(getline('.'))).'}\(.*\)$/\1'