Vim

如何反向匹配 Vim 程式語言中的字元串?

  • February 8, 2014

我想在字元串中找到[abc]集合中 任何字元的最後一個索引,abcabc但搜尋應該從字元串的末尾開始:

" Returns the 0th index but I want the 5th.
let a=match('abcabc', '[abc]')

:h functions我瀏覽了Vim 的“4. 內置函式” reverse(一個我不明白的限制,因為類似的函式len被設計成可以處理字元串、數字和列表。

為了解決這個問題,我想出了以下功能:

function! s:Rvrs(str)
 let a=len(a:str)      
 let b=a - 1
 let c=''
 while b >= 0
   let c.=a:str[b]
   let b-=1
 endwhile
 return c
endfunction

所以我可以說let a=match(s:Rvrs('abcabc'), '[abc]')

我環顧四周,但沒有找到任何看起來像它會做你想做的事情的內置函式。

不過,您可能會發現以下函式很有用:(包括從字元串開頭或結尾開始的重疊和非重疊匹配的變體;它們都支持多字元模式,但對\zs和/或的使用有一些限製或限制\ze)

function! s:AllOverlappableMatches(str, pat)
   " Restriction: a:pat should not use \ze
   let indicies = []
   let index = 0
   let splits = split(a:str, '\ze'.a:pat, 1)
   for segment in splits
       if len(segment) == 0
           call add(indicies, index)
       else
           let index += len(segment)
       endif
   endfor
   return indicies
endfunction
function! s:AllOverlappableMatchesFromEnd(str, pat)
   " Restriction: a:pat should not use \ze
   return reverse(s:AllOverlappableMatches(a:str, a:pat))
endfunction

function! s:AllNonoverlappingMatches(str, pat)
   " If a:pat uses \zs, the returned indicies will be based on that
   " position.
   " If a:pst uses \ze, subsequent matches may re-use characters
   " after \ze that were consumed, but not 'matched' (due to \ze)
   " in earlier matches.
   let indicies = []
   let start = 0
   let next = 0
   while next != -1
       let next = match(a:str, a:pat, start)
       if next != -1
           call add(indicies, next)
           let start = matchend(a:str, a:pat, start)
       endif
   endwhile
   return indicies
endfunction
function! s:AllNonoverlappingMatchesFromEnd(str, pat)
   " If a:pat uses \zs, the returned indicies will be based on that
   " position.
   let str = a:str
   let indicies = []
   let start = len(a:str) - 1
   while start >= 0
       let next = match(str, '.*\zs' . a:pat, start)
       if next != -1
           call add(indicies, next)
           let str = str[ : next - 1]
       endif
       let start -= 1
   endwhile
   return indicies
endfunction

echo s:AllOverlappableMatchesFromEnd('abcabc', '[abc]')
" -> [5, 4, 3, 2, 1, 0]

echo s:AllOverlappableMatchesFromEnd('dabcabc', '[abc]')
" -> [6, 5, 4, 3, 2, 1]

echo s:AllOverlappableMatchesFromEnd('dab - cabc', '[abc]')
" -> [9, 8, 7, 6, 2, 1]

echo s:AllOverlappableMatchesFromEnd('dab - cabce', '[abc]')
" -> [9, 8, 7, 6, 2, 1]

echo s:AllOverlappableMatchesFromEnd('dab - cabc', '[abc]\{2}')
" -> [8, 7, 6, 1]

echo s:AllOverlappableMatches('dab - cabc', '[abc]\{2}')
" -> [1, 6, 7, 8]              0123456789

echo s:AllNonoverlappingMatches('dab - cabc', '[abc]\{2}')
" -> [1, 6, 8]                   0123456789

echo s:AllNonoverlappingMatchesFromEnd('dab - cabca', '[abc]\{2}')
" -> [9, 7, 1]                          0123456789A

echo s:AllNonoverlappingMatchesFromEnd('ab - cabca', '[abc]\{2}')
" -> [8, 6, 0]                          0123456789

echo s:AllNonoverlappingMatchesFromEnd('abcabc', '[abc]\{2}')
" -> [4, 2, 0]                          012345

echo s:AllNonoverlappingMatchesFromEnd(' ab c abcd', '[abc]\{2}')
" -> [7, 1]                             0123456789

echo s:AllNonoverlappingMatchesFromEnd('abcabc', '[abc]\{2}')
" -> [4, 2, 0]                          012345

echo s:AllNonoverlappingMatches( 'abcabcabbc', 'abc')
" -> [0, 3]                       0123456789
echo s:AllNonoverlappingMatchesFromEnd( 'abcdabcabbc', 'abc')
" -> [4, 0]                              0123456789A

" A multi-character, overlappable pattern
echo s:AllOverlappableMatchesFromEnd( 'aaaabcaaac', 'aaa')
" -> [6, 1, 0]                         0123456789

如果我讀了這個問題,

echo match('abcabc', '.*\zs[abc]')

是一個答案:它將返回文本中最後一次出現模式的開頭。

如果您想要在最後一個之前的其他事件,'abcabc'[0:start_of_match+len(matched_string)-1]如果您想接受重疊,則必須剪切字元串才能處理(這在您的情況下沒有意義,因為您正在尋找[abc],而不是abc),或者'abcabc'[0:start_of_match-1]除此以外。

編輯:對不起,我錯過了克里斯約翰森的程式碼正在做的事情。

引用自:https://unix.stackexchange.com/questions/58529