如何在vim中使用regex来切换文件中所有字符的大小写

kse8i1jr  于 2022-11-11  发布在  其他
关注(0)|答案(2)|浏览(128)

我有一个文件,其中包含以下文本

Lorem IpSuM is SIMPLY duMMy TeXt of the PrINtinG and typesetting industry.
Lorem Ipsum has been the industry's stanDaRd dummy text ever since the 1500s,
whEn an unknown printer took a galley of type and sCrAMBled it to MakE a type specimen BoOk.

切换所有字符的大小写后,文本文件应如下所示:

lOREM iPsUm IS simply DUmmY tExT OF THE pRinTINg AND TYPESETTING INDUSTRY.
lOREM iPSUM HAS BEEN THE INDUSTRY'S STANdArD DUMMY TEXT EVER SINCE THE 1500S,
WHeN AN UNKNOWN PRINTER TOOK A GALLEY OF TYPE AND ScRambLED IT TO mAKe A TYPE SPECIMEN bOok.

我使用的正则表达式模式如下:

%s/\<\([A-Z\s\]+\)\>/\L&/

但是vi编辑器抛出一个错误:

E486: Pattern not found: \<\([A-Z\s\]+\)\>/\L&/

在vim中使用regex一次切换文件中所有字符大小写的正确模式是什么?

ybzsozfc

ybzsozfc1#

如果你能做ggShift+vG~,为什么还要用正则表达式和:s呢?
如果必须在脚本中执行此操作,可以使用:normal

:normal ggVG~

如果你真的想去:s,你可以这样做

%s/\a/\=submatch(0) >= 'a' && submatch(0) <= 'z' ? toupper(submatch(0)) : tolower(submatch(0))/g

(我怀疑有一种方法可以把submatch(0) >= 'a' && submatch(0) <= 'z'写得更简洁,但我不知道,或者我根本没有想到。romainl's answer说明了这一点。)

vh0rcniy

vh0rcniy2#

%s/\<\([A-Z\s\]+\)\>/\L&/

不是一个“模式”,只有那部分是:

\<\([A-Z\s\]+\)\>

请注意,Vim抱怨的是这种模式:

\<\([A-Z\s\]+\)\>/\L&/

这意味着Vim不能识别搜索部分和替换部分之间的分隔符。

\<\([A-Z\s\]+\)\>/\L&/
          ^

删除它会得到一个合适的替代命令,但Vim仍然说它找不到模式。让我们解构它来看看为什么...

  • \<\>表示您希望将模式锚定在单词的开头和结尾。
  • \(\)会分隔撷取群组,但您不会在取代中使用,因此没有必要。
  • +是一个字面量+,如果你想要“一个或多个前面的原子”,你需要\+。这可能就是多余的反斜杠的来源。
  • \s意味着你想在你的模式中包含一个空格,这和\<\>有点矛盾。

它 * 看起来 * 像你试图匹配的单词只由大写字符,这是没有意义的,因为你所说的目标。
然后在替换部分有\L,它使文本变成小写。如果你想切换大小写,把所有大写字符变成小写是无用的,因为这样你就不能再切换以前小写字符的大小写了,因为现在所有的字符都变成小写了。这不是一个好策略。
正如另一个答案所建议的那样,使用正常模式命令听起来是一个更好的策略。
至于替换,没有内置的相当于\L\U的“toggle”,因此您需要使用一点vimscript来增强替换部分:

:%s/./\=submatch(0) =~ '\L' ? toupper(submatch(0)) : tolower(submatch(0))

在那里...

  • \=告诉Vim使用表达式的结果作为替换,
  • 下面是一个三元条件,如果匹配项是小写的,则返回大写的匹配项; 2如果不是,则返回小写的匹配项。

请参阅:help sub-replace-special:help sub-replace-expression:help string-functions

相关问题