星期日, 六月 28, 2020

VIM学习笔记 模式行(Modeline)

程序员对于制表符常常有不同的偏好,有的使用8个空格,而有的则使用4个空格。可以想见,如果使用不同设置的用户操作相同的文件,必将对文本格式造成影响。

如果希望针对特定文件应用特定的设置,那么修改全局性的vimrc配置文件就显得小题大做了;而使用模式行(modeline),则可以将选项设置配置在文件本身当中。

例如将以下模式行放置到文件开头,将在打开该文件时设置制表符为4个空格:

/* vim:set tabstop=4: */

启用模式行

默认设置下,‘modeline’选项是打开的,Vim将会在文件的开头5行和结尾5行中查找模式行:

:set modeline

如果希望改变扫描的行数,那么可以设置‘modelines’选项:

:set modelines=1

定义以下快捷键,可以启用模式行并自动应用到当前文件,而不需要重新打开文件:

:nnoremap <leader>ml :setlocal invmodeline <bar> doautocmd BufRead<cr>

模式行主要有以下两种格式:

(1)不包含set命令的格式

  • [text{white}]{vi:|vim:|ex:}[white]{options}
  • 模式行将持续到行尾处结束;
  • 选项之间不能包含空格。

以下为正确的模式行:

/* vim:tabstop=4:expandtabs:shiftwidth=4 */

以下模式行选项中包含空格,将报错“Error E518: Unknown option: */”:

/* vim: noai:ts=4:sw=4 */

(2)包含set命令的格式

  • [text{white}]{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
  • 模式行将在第二个“:”处结束;
  • 模式行的开头和结尾可放置任意字符,建议使用“/* */”;
  • 开头字符之后的空格为必需的分隔符,不可以省略;
  • 选项之间以空格分隔。

以下为正确的模式行:

/* vim: set ai tw=75: */

以下模式行开头字符之后缺少空格,将无法生效,但不会报错:

/*vim: set tabstop=4: */

模式行实例

在Vim帮助文件的末尾,将发现以下模式行:

vim:tw=78:ts=8:noet:ft=help:norl:

其中,tw(textwidth)选项设置最大文本宽度为78;ts(tabstop)选项设置制表符为8个空格;noet(noexpandtab)选项设置为不扩展制表符;ft(filetype)选项设置文件类型为help;norl(norightleft)选项设置文本从左向右显示。

在Apache配置文件中,包含以下模式行:

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

其中,"#"标记本行为注释;syntax选项设置语法为apache;sw(shiftwidth)选项设置缩进为4个字符;sts(softtabstop)选项设置插入Tab时算作4个空格;sr(shiftround)选项设置缩进取整到'shiftwidth'的倍数。

通过使用模式行,可以确保文本被按照正确的格式展示,而不受本地设置的干扰。

禁用模式行

使用以下设置,Vim将不会查找模式行:

:set nomodeline

帮助信息

使用以下命令,可以查看当前设置:

:verbose set modeline? modelines?

使用以下命令,可以查看帮助信息:

:help 'modeline'

:help 'modelines'

命令小结
:set modeline启用模式行
:set modelines设置检查模式行的行数

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期六, 六月 20, 2020

VIM学习笔记 正则表达式-实例(Regex-Examples)

匹配空格

♦ 删除所有行首的空格:

:%s/^□□*\(.*\)/\1/

其中,使用^□□*查找行首的一个或多个空格;而\(.*\)将行中的其它内容捕获为组;在替换部分使用\1来恢复捕获组。

♦ 删除所有行尾的空格:

:%s/\(.*\)□□*$/\1/

其中,使用□□*$查找行尾的一个或多个空格;而\(.*\)将行中的其它内容捕获为组;在替换部分使用\1来恢复捕获组。

♦ 将多个空格替换为一个空格:

:%s/□□*/□/g

其中,第一个□代表一个实际的空格,而□*则会匹配零个或多个空格。

♦ 将冒号或句点之后的多个空格,替换为一个空格:

:%s/\([:.]\)□□*/\1□/g

其中,方括号内的的特殊字符(比如.)并不需要转义。

请在实际使用以上命令时,将其中“□”的替换为空格“ ”。

匹配换行

♦ 如果想要查找的内容之中包含换行符,那么可以使用"\n"通配符。执行以下命令,将匹配以"the"结尾的行,和以"word"开头的下一行:

/the\nword

♦ 如果希望同时匹配包含换行,以及不包含换行(但包含一个空格)的"the word",那么可以使用"\_s"匹配空格或换行:

/the\_sword

♦ 如果希望同时匹配包含多个空格以及换行的"the word",那么可以使用"+"通配符来匹配一次或多次:

/the\_s\+word

Regex_example_the_word

关于删除换行和空行,请参阅换行(Line Feed)章节。

匹配单复数

♦ 将单数单词,替换为复数:

:%s/^Note[□:s]*/Notes:□/g

其中,"Note[□:s]"将匹配"Note□","Notes", 和"Note:";而星号则会匹配零个后缀,即"Note"。

Regex-Examples-Singular

匹配包围的字符串

♦ 匹配引号包围的字符串(包含换行):

"\_[^"]*"

♦ 匹配特定单词包围的字符串(包含换行):

\(we\).*\1

其中,"\(we\)"将指定单词捕获为组,然后使用"\1"反向引用捕获组,以定义字符串的边界。

关于捕获组的详细介绍,请参阅捕获组(Groups)章节。

匹配章节编号

♦ 删除下图中黄色高亮区域,即行头以点分隔的章节号:

:%s/^[1-9][0-9]*\.[1-9][0-9.]*□//

Regex_example_remove_section_headings

其中,模式末尾的"[0-9.]*"可以继续匹配更多层级的章节号。

匹配序列号

♦ 匹配最少3个字符,最多16个字符,由字母和数字组成的用户名:

^[a-zA-Z0-9_-]{3,16}$

♦ 查找类似“1MGU103”的序列号。即由1个数字,3个大写字符和3个数字组成的字符串。可以使用以下几种不同的模式:

[0-9][A-Z]{3}[0-9]{3}

\d\u{3}\d{3}

\d\u\u\u\d\d\d

[[:digit:]][[:upper:]]{3}[[:digit:]]{3}

其中:

  • "[0-9]","\d","[:digit:]",均可匹配数字;
  • "[A-Z]","\u","[:upper:]",均可匹配大写字母;
  • "{3}",用于精确匹配3次。

Regex_example_serial_number

请注意,以上表达式均采用Very Magic模式。

匹配IP地址

♦ 匹配IPv4网络地址。即从"0.0.0.0"到"999.999.999.999"范围内的,以点分割的四段数字。

/\v([0-9]{1,3}[\.]){3}[0-9]{1,3}

但是以上命令,并不会判断数字串是否是一个有效的IP地址。比如"256.60.124.136"也会被匹配。但有效的IP地址中,每段数字均应为"0-255"。

♦ 匹配有效的IP地址。

/\v(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

Regex_example_ipv4

以上表达式分为四段重复的捕获组,每组数字的范围如下图所示:

Regex_example_ipv4_group

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 六月 14, 2020

VIM学习笔记 正则表达式-(vimgrep/grep)

在UNIX问世的前一年,1969年,Ken Thompson将正则表达式整合入QED文本编辑器。在Linux文本编辑器ed中,如果你希望显示包含字母“re”的行时,需要使用命令g/re/p,而grep也因此得名。可以看作此操作的缩写:g (globally), / (search), re (regular expression), / (delimit search), p (print)。

Vim提供以下两种grep(globally search a regular expression and print)搜索工具:

  • :vimgrep 使用Vim内置的grep实现;
  • :grep 调用外部的grep工具。

:grep命令会运行由选项grepprg所指定的程序。在Linux系统上,grepprg默认是grep -n:

grep_linux

在Windows系统上,grepprg默认是findstr /n

findstr

:vimgrep命令使用vim内置的搜索引擎,与/命令功能一致,但速度相对较慢。

由此可见,使用:vimgrep命令在不同平台上将获得一致的体验。而:grep命令则是与操作系统相关的,在不同平台会有不同的行为。

:grep:vimgrep命令,都将在QuickFix中显示搜索结果。

:lgrep:lvimgrep命令实现相同的功能,但使用地址列表(Location List)来显示匹配结果。

使用:copen命令打开的Quickfix,是全局性的。而使用:lopen打开的Location List,则是独立存在于各个窗口中的。

对于Quickfix,使用:cp命令,跳转到上一个匹配处;使用:cn命令,跳转到下一个匹配处。

对于Location List,使用:lpre命令,跳转到上一个匹配处;使用:lnext命令,跳转到下一个匹配处。

:vimgrep

使用以下命令,可以在当前目录下查找指定字符串:

:vimgrep grep *

如果希望在当前目录及其子目录中进行查找,那么可以使用**通配符:

:vimgrep blue **

以下命令将在当前目录及其子目录中的所有HTML文件中,查找指定字符串:

:vim blue **/*.html

请注意,:vimgrep命令可以缩写为:vim

首先在常规模式下,使用*命令查找光标下的单词;然后使用以下命令,可以重用之前的查找:

:vim // *.html

默认情况下,将自动跳转至第一个匹配处;如果希望停留在当前位置,那么可以在命令中使用j参选:

:vimgrep /foo/j **/*.md

使用以下命令,可以查看更多帮助信息:

:help :vimgrep

:grep

使用以下命令,将在当前目录下查找所有文件:

:grep block *.*

默认情况下,grep是区分大小写的,可以使用-i选项来忽略大小写:

:grep -i word filename

使用-o选项,将只显示匹配的字符,而不是整行内容:

:grep -o [[:punct:]] filename

使用以下命令,可以查看更多帮助信息:

:help :grep

请注意,递归搜索子目录的 **/*.* 通配符,对于Linux下的:vimgrep和:grep命令有效;但对于Windows下的:grep命令不起作用。

'grepprg'选项

使用以下命令,可以查看'grepprg'选项的当前设置:

:set grepprg?

在不同的操作系统下,Vim将默认使用不同的外部grep工具:

  • 在Windows下
    grepprg=findstr /n
  • 在Linux下
    grepprg=grep -n $* /dev/null

如果希望默认查询当前目录以及其子目录,那么可以使用以下设置:

  • 在Windows下
    set grepprg=findstr /S /n
  • 在Linux下
    set grepprg=grep -nR $* /dev/null

请注意,您可以使用:pwd命令来查看当前目录。

如果您在Windows中已经安装了GitCygwin,那么只需要在环境变量PATH中增加相应目录,即可调用其自带的grep命令:

  • C:\Program Files\Git\usr\bin
  • D:\cygwin64\bin

在Windows命令行中,可以使用以下命令进行验证:

$ grep --version

grep_version_win

然后在vimrc配置文件中,使用以下设置:

set grepprg=grep\ -rnIH\ --exclude-dir=.git

通过以上设置,可以在Windows环境中使用Linux风格的grep程序。

帮助信息

使用以下命令,可以查看更多帮助信息:

:help 'grepprg'

:help pattern

关于正则表达式的更多信息,可以参考以下网站:

使用以下网站,可以视觉化正则表达式,以便分步理解复杂的表达式:

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>

星期日, 六月 07, 2020

VIM学习笔记 增减数值(CTRL-A/CTRL-X)

常规模式下的CTRL-A/CTRL-X

Vim可以对文本进行简单的算术运算。在常规模式下,使用CTRL-A快捷键,可以将当前光标下的数字加1;使用CTRL-X快捷键,可以将当前光标下的数字减1。

通过在命令之前指定次数,可以增加或减少指定的数字。例如当前光标下数字为1,依次输入5Ctrl-A,数字将变为6(=1+5)。

如果在当前光标下未发现数值,那么将继续在本行内向后查找并执行增减操作。

使用以下命令,可以查看相关帮助信息:

:help CTRL-A

其它模式下的CTRL-A/CTRL-X

自Vim8以后,在可视化模式和选择模式下,也可以使用CTRL-ACTRL-X来增减数值(:help new-items-8)。

例如希望在第1条之后插入一个新的条目,那么就意味着需要调整后续各个条目的序号:

Article 1: 3 Steps To Enable Thesaurus Option
Article 2: Steps to Add Custom Header
Article 3: Automatic Word Completion
Article 4: How To Record and Play Macro
Article 5: Make Vim as Your C IDE

进入可视化模式,或者直接选择2-5行,然后点击CTRL-A即可对选中各行中的序号分别加1:

Article 1: 3 Steps To Enable Thesaurus Option
Article 3: Steps to Add Custom Header
Article 4: Automatic Word Completion
Article 5: How To Record and Play Macro
Article 6: Make Vim as Your C ID

在命令行中执行CTRL-A,也可以将第2行及之后各行中的序号分别加1:

:2,$g/\d\+/exe "normal! \<C-a>"

另外,您也可以使用替换字符串中的submatch()功能,实现相同的效果。

使用以下命令,可以查看相关帮助信息:

:help v_CTRL-A

'nrformats'选项

'nrformats'选项,用于控制CTRL-A和CTRL-X所识别的数字格式。

使用以下默认设置,Vim可以正确识别二进制和十六进制数;而十进制数,在所有设置下都可以被正确识别:

:set nrformats=bin,hex

使用以下命令清空选项,将所有数字识别为十进制:

:set nrformats=

如果希望只识别八进制数,那么可以使用以下命令:

:set nrformats=octal

如果在选项中增加"alpha",那么也可以选择上一个和下一个字母:

:set nrformats+=alpha

以下表格,列示了针对“原始值”,分别点击CTRL-ACTRL-X所产生的效果:

选项值CTRL-X原始值CTRL-A说明
十进制012以1-9开头的数值
-2-10
二进制bin0b01110b10000b1001以"0b"或"0B"开头的数值
八进制octal006007010以0开头的数值
十六进制hex0x0ff0x1000x101以"0x"或"0X"开头的数值
字母alphaBCD
AAB针对第一个字母"A"执行CTRL-X无作用
YZZ针对最后一个字母"Z"执行CTRL-A无作用

使用以下命令,可以查看相关帮助信息:

:help 'nrformats'

自定义CTRL-A/CTRL-X键盘映射

在Windows下的Vim中,使用以下命令可以看到vimrc自动加载了mswin.vim文件,CTRL-A已经被映射为选择全部,而CTRL-X则被映射为剪切:

:verbose map <C-a>

verbose_map_CTRL-A

使用以下命令,可以取消针对CTRL-A的键盘映射,以恢复其增加数值的功能:

:unmap <C-a>

如果希望保留当前Windows习惯的键盘映射,那么可以新增以下基于前缀键(leader)的定义:

:vnoremap <leader>a <C-a>

:vnoremap <leader>x <C-x>

命令小结
CTRL-A增加数值
CTRL-X减少数值
:set nrformats控制CTRL-A和CTRL-X所识别的数字格式

Ver: 2.0 | YYQ<上一篇 | 目录 下一篇>