例如:我想将所有
1
替换为0
,同时将所有0
替换为1
[
[1, 1, 1, 1, 1, 0],
[1, 1, 1, 1, 0, 1],
[1, 1, 1, 0, 1, 1],
[1, 1, 0, 1, 1, 1],
[1, 0, 1, 1, 1, 1],
[0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 0],
]
#1 楼
是的,您可以通过使用表达式来实现。对于这种特殊情况,您可以使用Vim算术并计算1-x
,它将把0变成1,将1变成0。:s/\d/\=1-submatch(0)/g
对于更一般的替换情况,您可以可以使用Dict存储匹配到替换字符串的映射。
例如,将数字转换为书面数字:
:let repl = {"0": "zero", "1": "one"}
:s/\d/\=repl[submatch(0)]/g
请参阅:
:help sub-replace-expression
:help /\d
:help submatch()
:help Dict
#2 楼
这里已经有很多很好的答案,但是为了完整起见,我觉得我应该指出,在大多数实际情况下,如果将多个ex命令与条形码字符|
连接起来,它们的作用就像一个操作。 /> 特别地,它们将导致每个撤消树和更改列表中的单个项。 1:
:%s/1/TEMP/g | %s/0/1/g | %s/TEMP/0/g
#3 楼
在您的特定用例中,我认为您可以在网上方便地进行操作:#4 楼
确定:%s/[01]/\="10"[submatch(0)]/g
匹配
0
或1
并用"10"[0]
= 1
"10"[1]
= 0
#5 楼
这个答案比其他答案更长,它没有利用特定的数据值优势,这是用n个不同的替换项替换n个不同的值的通用解决方案:let d={0:1,1:0} | %s/\v(0|1)/\=d[submatch(0)]/g | unlet d
如果您想一次更换将Hello vim 8
更改为Oh god 9
:let d={'Hello':'Oh','vim':'god',8:9} | %s/\v(Hello|vim|8)/\=d[submatch(0)]/g | unlet d
#6 楼
我真的很惊讶,vi / vim中没有本机tr
,但是如果您的平台足够UNIXy,那么就有一个用于此的外部命令:我个人会用的东西,但可能不够便携。
评论
有:h tr()
–克里斯蒂安·布拉班特(Christian Brabandt)
20-04-30在20:24
从函数中,我们可以定义一个命令:请参见stackoverflow.com/a/25665554/15934
–卢克·赫米特(Luc Hermitte)
20-04-30在22:37
#7 楼
我很确定我已经在vi.SE或stackoverflow上对一般情况给出了答案,但是找不到Q / A ...提供以下命令可以在您的情况下使用的命令CycleSubstitute
:[range]CycleSubstitute/0/1
我已经将其打包在这里。它是通过以下方式实现的:
:command! -bang -nargs=1 -range CycleSubstitute <line1>,<line2>call s:CycleSubstitute("<bang>", <f-args>)
function! s:CycleSubstitute(bang, repl_arg) range
let do_loop = a:bang != "!"
let sep = a:repl_arg[0]
let fields = split(a:repl_arg, sep)
let cleansed_fields = map(copy(fields), 'substitute(v:val, "\\[<>]", "", "g")')
" build the action to execute
let action = '\=s:DoCycleSubst('.do_loop.',' . string(cleansed_fields) . ', "^".submatch(0)."$")'
" prepare the :substitute command
let args = [join(fields, '\|'), action ]
let cmd = a:firstline . ',' . a:lastline . 's'
\. sep . join(fields, '\|')
\. sep . action
\. sep . 'g'
" echom cmd
" and run it
exe cmd
endfunction
function! s:DoCycleSubst(do_loop, fields, what)
let idx = (match(a:fields, a:what) + 1) % len(a:fields)
return a:fields[idx]
endfunction
#8 楼
类似于@LucHermitte的答案,SwapStrings插件使您可以执行:%SwapStrings 0 1
我自己的PatternsOnText插件提供了
:SubstituteMultiple
命令(除其他外),该命令可以作为特例进行交换原子进行多次替换(即不引入临时替换)的方法::%SubstituteMultiple /0/1/ /1/0/ g
#9 楼
要添加到允许这样做的插件列表中,vim-abolish具有Subvert
函数,可以利用它来实现多次替换:%Subvert/{1,0}/{0,1}/g
#10 楼
:%s/\([01]\)/\=1-submatch(1)/g
替换命令中发生以下情况
搜索1或0,将其记住为子匹配项1(在第一个/和第二个/之间)
通过从1(第二个和第三个/之间)减去值来替换值。
1变为0,0变为1
<=替换部分中的表达式
评论
欢迎来到Vi和Vim!好的答案通常会在代码旁边提供解释,以便提供指导
– D. Ben Knoble♦
20年5月1日下午1:29
评论
我喜欢这种解决方案;另一种则更聪明,并且可以说是更好的,但是这一点更容易记住并且认知负荷较低。有时候,我花费更多的时间使“聪明”的方法生效,而不是仅仅使用“愚蠢”的方法所节省的时间。也许我不够聪明,呵呵
–马丁·图尔诺伊(Martin Tournoij)
20年4月30日在18:15