Regex Vim正则表达式用于拆分字符串,但保留分隔符

Regex Vim正则表达式用于拆分字符串,但保留分隔符,regex,vim,Regex,Vim,根据我目前的理解,下面的模式应该可以工作(预期['bar',FOO','bar']),但只找到了第一个备选方案(FOO之后的零宽度匹配,而不是之前的零宽度匹配) echo split('barFOObar','\v(FOO\zs | \zeFOO)')-->['barFOO','bar'] 我可以用向前看/向后看来解决它吗 echo split('barFOObar','\v((FOO)\@您可以先将FOO替换为-FOO-,然后拆分字符串。例如: :echo split(substitute(

根据我目前的理解,下面的模式应该可以工作(预期
['bar',FOO','bar']
),但只找到了第一个备选方案(FOO之后的零宽度匹配,而不是之前的零宽度匹配)

echo split('barFOObar','\v(FOO\zs | \zeFOO)')-->['barFOO','bar']
我可以用向前看/向后看来解决它吗


echo split('barFOObar','\v((FOO)\@您可以先将
FOO
替换为
-FOO-
,然后拆分字符串。例如:

:echo split(substitute('barFOObarFOObaz', 'FOO','-&-','g'),'-')
['bar', 'FOO', 'bar', 'FOO', 'baz']
function! SplitDelim(expr, pat)
    let result = []
    let expr = a:expr
    while 1
        let [w, s, e] = matchstrpos(expr, a:pat)
        if s == -1
            break
        endif
        call add(result, s ? expr[:s-1] : '')
        call add(result, w)
        let expr = expr[e:]
    endwhile
    call add(result, expr)
    return result
endfunction

您可以先将
FOO
替换为
-FOO-
,然后拆分字符串。例如:

:echo split(substitute('barFOObarFOObaz', 'FOO','-&-','g'),'-')
['bar', 'FOO', 'bar', 'FOO', 'baz']
function! SplitDelim(expr, pat)
    let result = []
    let expr = a:expr
    while 1
        let [w, s, e] = matchstrpos(expr, a:pat)
        if s == -1
            break
        endif
        call add(result, s ? expr[:s-1] : '')
        call add(result, w)
        let expr = expr[e:]
    endwhile
    call add(result, expr)
    return result
endfunction

使用单个
split()
似乎无法实现直接结果。事实上,
split()
的文档提到了保留分隔符的这种特殊情况,其中包括:

如果要保留分隔符,也可以在图案末尾使用
\zs

:echo split('abc:def:ghi', ':\zs')
['abc:', 'def:', 'ghi']
话虽如此,同时使用lookahead和lookahead确实有效。在您的示例中,您有一个语法错误。由于您使用的是verymagic模式,您不应该逃避
@
,因为它已经很特殊了。(感谢您指出!)

这项工作:

:echo split('barFOObar', '\v((FOO)@<=|(FOO)@=)')
" --> ['bar', 'FOO', 'bar']
这里遇到的第一个问题是,
|
两侧的两个表达式都匹配相同的文本“FOO”,因此,由于它们是相同的,第一个表达式获胜,而您在左侧得到它

更改订单后,您会在右侧看到它:

:echo split('barFOObar', '\v(\zeFOO|FOO\zs)')
" --> ['bar', 'FOObar']
现在的问题是,为什么第二个标记“FOObar”没有被拆分,因为它再次匹配(lookback案例拆分了这个标记,对吗?)

好的,答案是它实际上再次被拆分,但它再次匹配了
\zeFOO
的第一种情况,并生成了一个空字符串拆分。通过传递KeepImpty参数可以看到:

:echo split('barFOObar', '\v(\zeFOO|FOO\zs)', 1)
" --> ['bar', '', 'FOObar']

这里仍然没有回答的一个问题是,为什么lookahead/lookback可以工作,而
\zs
\ze
不能工作。我想我在语法组中的regex用法中解决了这个问题

这不会起作用,因为Vim不会两次扫描相同的文本以匹配不同的正则表达式

即使
\zs
使结果匹配只包含
,Vim也需要使用
FOO
才能匹配该正则表达式,如果它已经将其与模式的另一半匹配,则不会这样做


使用
\@的lookback似乎没有办法使用单个
split()
实现直接结果。事实上,
split()
的文档提到了保留分隔符的这种特殊情况,包括:

如果要保留分隔符,也可以在图案末尾使用
\zs

:echo split('abc:def:ghi', ':\zs')
['abc:', 'def:', 'ghi']
话虽如此,同时使用lookahead和lookahead确实有效。在您的示例中,您有一个语法错误。由于您使用的是verymagic模式,您不应该逃避
@
,因为它已经很特殊了。(感谢您指出!)

这项工作:

:echo split('barFOObar', '\v((FOO)@<=|(FOO)@=)')
" --> ['bar', 'FOO', 'bar']
这里遇到的第一个问题是,
|
两侧的两个表达式都匹配相同的文本“FOO”,因此,由于它们是相同的,第一个表达式获胜,而您在左侧得到它

更改订单后,您会在右侧看到它:

:echo split('barFOObar', '\v(\zeFOO|FOO\zs)')
" --> ['bar', 'FOObar']
现在的问题是,为什么第二个标记“FOObar”没有被拆分,因为它再次匹配(lookback案例拆分了这个标记,对吗?)

好的,答案是它实际上再次被拆分,但它再次匹配了
\zeFOO
的第一种情况,并生成了一个空字符串拆分。通过传递KeepImpty参数可以看到:

:echo split('barFOObar', '\v(\zeFOO|FOO\zs)', 1)
" --> ['bar', '', 'FOObar']

这里仍然没有回答的一个问题是,为什么lookahead/lookback可以工作,而
\zs
\ze
不能工作。我想我在语法组中的regex用法中解决了这个问题

这不会起作用,因为Vim不会两次扫描相同的文本以匹配不同的正则表达式

即使
\zs
使结果匹配只包含
,Vim也需要使用
FOO
才能匹配该正则表达式,如果它已经将其与模式的另一半匹配,则不会这样做


\@的lookbehind拆分后,你能用
*FOO*
这样的字符串连接,然后在
*
上再次拆分吗?效率不高,但可能没关系。
我能不能用lookbehind/lookbehind解决这个问题。
你的正则表达式中有一个错误,如果你使用
\v
,你不应该逃避lookaround。试试看这:
echo分割('barFOObar','\v((FOO)@@user938271哇,非常感谢:)这个问题基本上已经解决了,但是我仍然想知道第一个版本使用
\zs
&
\ze
的行为,但是我仍然想知道第一个版本使用\zs&\ze
\zs
\ze
限制正则表达式匹配的文本的行为,但是在内部,整个文本仍然是ma已匹配,当正则表达式具有重叠匹配时(一旦删除
\zs
\ze
)。语法规则也存在同样的缺陷;请参阅。拆分后,是否可以使用类似于
*FOO*
的字符串进行连接,然后在
*
上再次拆分。效率不高,但可能没什么关系。
我是否可以使用lookahead/lookahead解决此问题。
:正则表达式中有错误,如果使用
\v
。试试这个:
回音分割('barFOObar','\v((FOO)@@user938271哇,非常感谢:)这个问题基本上已经解决了,但是我仍然想知道第一个版本使用
\zs
&
\ze
的行为,但是我仍然想知道第一个版本使用\zs&\ze
\zs
\ze
的行为限制了正则表达式匹配的文本,但是在内部,整个文本是不匹配的