Vim实用技巧进阶(第12章:匹配模式和文本)

您所在的位置:网站首页 vim快速搜索整个字段的内容 Vim实用技巧进阶(第12章:匹配模式和文本)

Vim实用技巧进阶(第12章:匹配模式和文本)

2024-07-11 22:30| 来源: 网络整理| 查看: 265

Practical.Vim.2nd.Edition 实用技巧进阶 第12章:模式和文本匹配

第12章 匹配模式和文本

Matching Patterns and Literals

本章节我们将讨论 搜索, 替换和全局(search,substitute,global)命令. 不过首先得专注于其驱动的核心: Vim搜索引擎. 是否有思考过 Vim 正则表达式是如何工作, 如何关闭正则来进行匹配呢?

Vim 的正则表达式引擎可能与我们习惯使用的引擎有些不同. 最大的差异是可以通过 神奇开关 来切换模式进行搜索. 默认情况下, 某些字符在搜索时有特殊含义, 搜索时需要进行转义. 后续我们将学习如何使用 \V开关 一次性禁用所有的特殊含义

Vim 搜索模式中有几个特殊的选项: 零宽度分隔符, 用来标记单词或搜索匹配的边界. 后面我们将学习如何使用 \V文字开关 来处理特殊字符

Tip 73 调整搜索大小写敏感度

Tune the Case Sensitivity of Search Patterns

我们可以控制全局或每一次搜索是否开启忽略大小写

全局区分大小写

通过设置 ignorecase 选项即可开启忽略大小写:

➾ :set ignorecase

需要注意的是, 此设置会对 Vim 关键词补全有一定的影响 参考:[Tip 112 关键词补齐]

每次搜索区分大小写

我们可以使用以下选项来覆盖默认的是否忽略大小写:

\c - 忽略大小写 \C - 区分大小写

每次搜索的时候都可以强制指定是否区分大小写

所以, 如果想强制区分大小写, 只需要在每次敲完 pattern 之后加上 \C 即可

启用智能大小写

Vim 提供了预测我们大小写敏感意图的 smartcase 选项

启用此选项后进行搜索时, 如果输入的全部是小写字母, 那么就不区分大小写; 但只要包含大写字母, 那么就是大小写敏感的

2个选项开启和关闭的搜索表现:

Pattern 'ignorecase' 'smartcase' Matches foo off - foo foo on - foo Foo FOO foo on on foo Foo FOO Foo on on Foo Foo on off foo Foo FOO \cfoo - - foo Foo FOO foo\C - - foo

手册:

:h /ignorecase :h smartcase Tip 74 使用\v启用正则搜索

Use the \v Pattern Switch for Regex Searches

Vim 正则表达式语法风格比起 Perl 来说更接近 POSIX, 对于已经熟悉 Perl 的程序员来说有点失望了; 对于两种语言都不懂的表示更忧伤 :(

不过可以通过一个神奇的开关使得 Vim 的语法更接近于 正则表达式

颜色编码匹配 patterns/color.css

body { color: #3c3c3c; } a { color: #0000EE; } strong { color: #000; }

需要匹配 # 号后面的3位或6位 16进制 的字符, 包含数字和 A-F 的大小写字母

匹配16进制的颜色编码

Vim 默认的模式:神奇模式 (magic search)

➾ /#\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\)

这里使用了3中类型的括号:

[] 中括号(Square brackets), 具有特殊的含义, 所以这里不需要转义 () 小括号(parentheses), 字面上匹配 () 2字符, 所以我们必须转义它们以使它们具有特殊含义 {} 大括号(curly braces), 和小括号一样, 但只用转义开头的一半即可

3种不同的括号决定了不同的规则, 这个一定需要记住!!!

两个正则表达式引擎

Vim 7.4 引入了一个新的正则表达式引擎. 就的引擎使用回朔算法, 而新引擎使用状态机(state machine), 对复杂模式和长文本执行得更好. 相应的, 这种增强提高了使用正则表达式的所有特性(如语法高亮, 命令搜索 和 vimgrep)的性能

Vim 7.4 默认是启用的新的引擎的, 但旧的引擎仍然可以使用. 一些 Vim 正则表达式的特性不支持新的引擎. Vim 会自动切换到老的引擎来进行支持

手册:

:h new-regexp-engine :h two-engines 使用\v切换匹配模式

我们可以使用 \v 模式(very magic search)开关规范所有的特殊符号, 启用之后, 除了下划线 _, 大小写字母, 和数字外, 所有的字符都具有特殊含义

开启 \v 模式后, Vim 正则表达式引擎的行为表现得更像 Perl, Python 或 Ruby. 但是仍然有不同的地方, 后续的小节将会介绍哪些规则需要转义, 哪些不需要转义

➾ /\v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})

少了很多的转义的反斜杠, 看起来是不是更加简洁了

手册 :h \v

使用字符类简化匹配

针对本示例, 我们有更加优雅的字符类 \x 来进行匹配, 而不用再去拼写复杂的 [0-9a-fA-F] 字符串

➾ /\v#(\x{6}|\x{3})

手册 :h /character-classes

讨论 匹配模式 说明 #\([0-9a-fA-F]\{6}\|[0-9a-fA-F]\{3}\) 默认(\m)模式, ()|{ 需要转义 \v#([0-9a-fA-F]{6}|[0-9a-fA-F]{3}) \v 模式, ()|{ 已有特殊含义, 不用转义 \v#(\x{6}|\x{3}) 用 \x 字符类表示了 [0-9A-Fa-f] 字符集

Vim 认为所有还没有特殊意义的字符都是为 将来扩展保留 的. 换句话说, 例如 # 号现在没有特殊的含义不代表以后的版本中不会有特殊的含义. 如果 # 号已经有特殊含义了, 那么就需要转义来匹配 # 字符

手册 :h /\\

Tip 75 使用\V启用文本搜索

Use the \V Literal Switch for Verbatim Searches

Vim 正则表达式的特殊字符在匹配时很方便, 但如果我们想搜索这些字符时, 它们可能会受到影响. 使用 verynomagic 文字开关可以取消诸如 . * 和 ? 等字符的特殊含义

patterns/excerpt-also-known-as.txt

The N key searches backward... ...the \v pattern switch (a.k.a. very magic search)...

例如我们先搜索 a.k.a 那么最直观的搜索则为:

➾ /a.k.a.

不过但我们按下回车, 我们匹配到的比我们期望的多, 因为 . 字符有特殊的含义, 可以表示任意一个字符, 我们可以加个反斜杠(\)来进行转义来使用其字面含义

Keystrokes Buffer Contents {start} The N key searches backward… …the \v pattern switch (a.k.a. very magic search)… /a.k.a. The N key searches backward… …the \v pattern switch (a.k.a. very magic search)… /a\.k\.a. The N key searches backward… …the \v pattern switch (a.k.a. very magic search)… /\Va.k.a. The N key searches backward… …the \v pattern switch (a.k.a. very magic search)…

本示例中, 我们使用 /a.k.a. 进行搜索哦时, 出现了2处匹配的位置, 第二个才是我们期望的匹配, 我们也可以按 n 快速移动

不过在某些情况下, 一个不精准的匹配可能导致奇怪的问题, 例如在执行 :%s//also known as/g 替换时, 会发现替换多了(替换时如果不指定搜索内容, 那么默认指上一次的搜索模式, 参考: Tip 91)

由于 . 字符有特殊含义(匹配任意字符), 所以如果想匹配 . 字符, 那么就需要加反斜杠(\)进行转义:

➾ /a\.k\.a\.

或者使用 \V 的纯字符模式:

➾ /\Va.k.a.

Vim 文档里提到 “使用 \V 模式意味着后面的搜索匹配只有反斜线(\)和终止符(/或?)具有特殊含义” 在 Tip 79 的转义问题字符将介绍更多信息

按照经验: 使用 \v 开关来启用正则搜索, 而使用 \V 开关启用纯文本搜索

手册 :h /\V

历史课:Vim模式语法遗产

除了 \v 和 \V 模式外, Vim 还有两种比较旧的匹配模式 (此4种模式仅Vim特有)

\m - magic search Vim默认的神奇搜索, 自动为少数额外符号赋予特殊含义, 例如:.*[], 但是没有给 +?(){} 赋予特殊含义, 这些字符必须转义才能赋予它们特殊含义 (对应正则表达式特殊的支持只走了一半, 看起来规则比较随意, 难以记忆) \v - very magic search 非常神奇搜索, 启用后语法更贴近 正则表达式, 除了 _a-zA-Z 之外的每个符号都有特殊含义, 语法和 Perl 正则一致 \V - verynomagic 纯文本搜索, 所有字符都没有特殊含义 (除了反斜杠和终止符) \M - nomagic 普通搜索(没有魔法), 和纯文本类似, 模拟 vi 的搜索, 除了2个字符: ^ 和 $ Tip 76 使用括号捕获子匹配

Use Parentheses to Capture Submatches

当我们进行搜索匹配时, 我们可以使用括号()捕获子匹配, 然后在其他地方引用他们. 此功能与替换(substitute)命令配合是非常有用!!!

patterns/springtime.txt

I love Paris in the the springtime.

上面片段中有词汇语法错误, the 出现了2次, 中间还有换行, 我们来使用搜索匹配来进行替换

➾ /\v

嗯, 已经把2个重复的次 the the 匹配到了. 这个时候如果把2行合并成一行(vipJ进行合并)同样是可以匹配的. 最棒的是, 此模式可以匹配所有重复的2个单词.

我们下面介绍此正则是如何起作用的:

2次匹配相同单词的技巧在于 () 和 \1 的组合使用. 括号内的任何内容都会自动存入到一个临时仓库中, 然后使用 \1 引用捕获到的文本内容. 如果模式中包含多组括号, 那么我们可以依次使用 \1, \2 … \9 来引用捕获的内容(最多到\9). \0 表示引用整个匹配内容, 不管模式中是否有括号

正则表达式在匹配词汇的时候有很多的小技巧. 我们在 Tip 74 介绍了使用 \v 开关启用正则搜索. 而 字符可以匹配单词的边界, 这个后续再 Tip 77 中在做介绍. 最后, \_s 匹配空白字符或换行符

子匹配在搜索模式中很有用. 不过有一个很好的示例就是: XML 和 HTML 标签的开始和结束匹配. 在 Tip 94 会介绍子匹配的替换

手册:

:h /\_ :h 27.8 使用括号而不捕获内容 搜索测试: Andrew 或 Drew ➾ /\v(And|D)rew Neil 在括号前面使用 % 符号, 禁当前组的捕获 ➾ /\v%(And|D)rew Neil FIRSTNAME LASTNAME 位置互换 ➾ /\v(%(And|D)rew) (Neil) ➾ :%s//\2, \1/g

使用 %() 匹配的组将不计入捕获结果, 最后一次搜索一共有3组括号, 所以第1组括号 \1 对应的捕获内容为 And 或 D, 第2组括号因为前面有 % 符号, 所以不捕获, 第3组括号由于前面只有一个捕获的, 所以依次算作 \2, 对应的捕获内容为 Neil; 最后替换的效果就是2个词互换位置

Tip 77 标注词的边界

Stake the Boundaries of a Ward

定义一个搜索模型时, 指定单词的开始和结束位置可能很有用, Vim 给我们提供了单词分隔的选项

例如执行搜索 /the 的时候, 是会把 these they their 等单词一起搜索出来的

the problem with these new recruits is that they don't keep their boots clean.

如果我们想只搜索 the 完整的单词, 而不需要包含 the 片段的词, 那么我们需要指定 词的边界

在 \v 模式下, 即代表词边界的符号. 所以我们可以使用 /\v 来达到我们的预期

是 0长度 的选项, 意味着他们本身不匹配任何字符. 他们只是表示一个 单词 与 空格或标点 之间的边界

我们可以大致认为 的含义和 \w,\W 字符类与 \zs,\ze 匹配分隔符的组合相似(参考 Tip 78).

\w - 匹配一个单词的字符. 包括字母, 数字和下划线_字符 \W - 匹配非了单词外的其他任意字符 接近于 \w\ze\W

在 \v 模式(very magic)下, 符号 代表一个词的边界, 但是在 \m, \M \V 模式(magic, nomagic, very nomagic)下, 就需要转义.

因此, 我们使用 Vim 文档进行查看时也是需要加转义的反斜杠的 :h /\



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3