有没有一种方法可以替换matchlist()
中的子匹配并用它修改原始行?我喜欢编写一个脚本,用一步修改模式中的所有子匹配(可以是用户想要的任何内容)。
对于示例,原始行为some AfooBar
,用户希望将其更改为some CfooDar
。
思考通用解决方案,适用于任何模式:
let pattern = '\(A\)foo\(B\)'
let line = 'some AfooBar'
let found = matchlist( line, pattern )
found
包含['AfooB', 'A', 'B', '', '', '', '', '', '', '']
。现在我必须修改line
到some CfooDar
,所以最好的方法是通过修改其中的数字来重用matchlist()数组,然后“编译”该行:
let found[1] = 'C'
let found[3] = 'D'
let line = MATCHLIST_TO_STRING( found )
据我所知,内置函数不可能,所以我需要写一个。在匹配之前不会修改该行的开头,因此我可以将该部分复制到'new_line':
let new_line = strpart( line, 0, match( line, pattern ) )
但在这一点上我不知道如何继续。我可以立即附加修改后的A
,因为模式以它开头(在此示例中,但用户可以使用任何类型的模式)。但是我怎样才能找到foo
和B
的(偏移)索引?在这个例子中,它很简单,因为行中没有其他foo
和B
,但让我们看另一个例子:
let line = 'A A A A A'
let pattern = 'A \(A\) A \(A\)'
如果我想将其修改为A B A C A
,则很难检测到line
中子匹配的位置。
一种解决方案是使用“内部单词”的子匹配(如上例中的foo
),但它会减少有用的子匹配数。例如:
let pattern = '\(A\)\(foo\)\(B\)'
let line = 'some AfooBar'
let found = matchlist( line, pattern )
" Remove the full match, we need only the submatches.
call remove( found, 0 )
let found[0] = 'C'
let found[2] = 'D'
let new_line = strpart( line, 0, match( line, pattern ) ) . join( found, '')
在这种情况下,我们使用了一个额外的子匹配,但A \(A\) A \(A\) A
可能会变成\(A \)\(A\)\( A \)\(A\)\( A\)
并且它太多了。
那么有没有一种方法可以在一个步骤中用新值替换所有子匹配?
答案 0 :(得分:0)
整个问题都是XY的味道。那么询问您的初始问题而不是您的非工作解决方案呢?
简单:
call setline('.', substitute(getline('.'), 'A\(foo\)B', 'C\1D', 'g'))
更简单:
s/A\(foo\)B/c\1D/g