Регекси 1

20 април 2023

Административни неща

Преговор

Преговор

Преговор

Преговор

Регекси: история

Регекси: история

Регекси: история

Регекси: история

Регекси: преди да започнем

Пълен reference, от синтактична конструкция до списък на pattern-ите, може да намерите във :help pattern.txt. Не е нужно да ги помните, винаги може да намерите цялата информация от ^ до $.

Списъка на индивидуалните специални символи започва от :help pattern-overview.

Целта на лекцията е по-скоро да разберете механизмите и да ви дам акъл кои неща са полезни и кои не чак толкова (както всички лекции, I guess). С времето ще изградите интуиция.

Регекси: основни неща

Търсим шаблони с /<pattern>, пример:

1 2 3 4 5 6 7
foo
fooooo
fo
f
foo+bar
foo*bar
foobar

Регекси: основни неща

Търсим шаблони с /<pattern>, пример:

1 2 3 4 5 6 7
foo
fooooo
fo
f
foo+bar
foo*bar
foobar

Регекси: основни неща

Търсим шаблони с /<pattern>, пример:

1 2 3 4 5 6 7
foo
fooooo
fo
f
foo+bar
foo*bar
foobar

Регекси: основни неща

Мапинга * добавя "word boundaries":

Регекси: Основни неща

Регекси: Основни неща

Регекси: Основни неща

Регекси: Основни неща

Регекси: Основни неща

Регекси: non-greedy варианти

:help /\{ -- greedy

1 2 3 4 5
\{n,m}  n to m          as many as possible
\{n}    n               exactly
\{n,}   at least n      as many as possible
\{,m}   0 to m          as many as possible
\{}     0 or more       as many as possible (same as *)

Регекси: non-greedy варианти

:help /\{ -- greedy

1 2 3 4 5
\{n,m}  n to m          as many as possible
\{n}    n               exactly
\{n,}   at least n      as many as possible
\{,m}   0 to m          as many as possible
\{}     0 or more       as many as possible (same as *)

:help /\{- -- non-greedy

1 2 3 4 5
\{-n,m} n to m          as few as possible
\{-n}   n               exactly
\{-n,}  at least n      as few as possible
\{-,m}  0 to m          as few as possible
\{-}    0 or more       as few as possible

Регекси: non-greedy варианти

Регекси: групиране

Регекси: групиране

Регекси: групиране

Регекси: групиране

Регекси: групиране

Регекси: групиране

Регекси: специални класове от символи

:help /\i

Регекси: специални класове от символи

:help /\i

Регекси: специални класове от символи

:help /\i

Регекси: специални класове от символи

:help /\i

Регекси: специални класове от символи

:help /\i

Регекси: специални класове от символи

В рамките на [], за голяма досада, character класове като \d или \k не работят. Но имаме [:digit:] и [:keyword:].

Списъка започва от :help [:alnum:]

Регекси: whitespace

Регекси: whitespace

Регекси: whitespace

Регекси: whitespace

Регекси: whitespace

Регекси: backreference

Веднъж като сме групирали нещо с \(\), можем да го реферираме като \1, втората такава група е \2, etc. (Групата \0 е целия match, което е единствено полезно за substitution-и после.) В документацията това се нарича "subexpression", другате "submatch" или "capture group".

Регекси: backreference

Веднъж като сме групирали нещо с \(\), можем да го реферираме като \1, втората такава група е \2, etc. (Групата \0 е целия match, което е единствено полезно за substitution-и после.) В документацията това се нарича "subexpression", другате "submatch" или "capture group".

За да мачнем само многоредовия низ, \(\u\+\)\_.*\1:

1 2 3 4 5 6 7
code = <<~EOF
  example_text
EOF

other_code = <<~SQL
  select * from users
SQL

Регекси: backreference

Веднъж като сме групирали нещо с \(\), можем да го реферираме като \1, втората такава група е \2, etc. (Групата \0 е целия match, което е единствено полезно за substitution-и после.) В документацията това се нарича "subexpression", другате "submatch" или "capture group".

За да мачнем само многоредовия низ, \(\u\+\)\_.*\1:

1 2 3 4 5 6 7
code = <<~EOF
  example_text
EOF

other_code = <<~SQL
  select * from users
SQL

Регекси: branching

:help pattern -- |, \&

Регекси: branching

:help pattern -- |, \&

Регекси: branching

:help pattern -- |, \&

Регекси: branching

:help pattern -- |, \&

Регекси: branching

:help pattern -- |, \&

Magic

:help magic

Magic: very magic

Very magic mode: Започва със \v

Magic: very magic

Very magic mode: Започва със \v

Magic: very magic

Very magic mode: Започва със \v

1 2
Use of "\v" means that after it, all ASCII characters except '0'-'9', 'a'-'z',
    'A'-'Z' and '_' have special meaning: "very magic"

Magic: very magic

Magic: very NOmagic

Very nomagic mode: Започва със \V

1 2
Use of "\V" means that after it, only a backslash and the terminating
character (usually / or ?) have special meaning: "very nomagic"

Magic: very NOmagic

Very nomagic mode: Започва със \V

1 2
Use of "\V" means that after it, only a backslash and the terminating
character (usually / or ?) have special meaning: "very nomagic"

Magic: very NOmagic

Very nomagic mode: Започва със \V

1 2
Use of "\V" means that after it, only a backslash and the terminating
character (usually / or ?) have special meaning: "very nomagic"
1 2
let user_input = input("Search for a string: ")
exe '/\V' .. escape(user_input, '/\')

Magic: very NOmagic

Very nomagic mode: Започва със \V

1 2
Use of "\V" means that after it, only a backslash and the terminating
character (usually / or ?) have special meaning: "very nomagic"
1 2
let user_input = input("Search for a string: ")
exe '/\V' .. escape(user_input, '/\')

или,

1 2
let user_input = input("Search for a string: ")
call search('\V' .. escape(user_input, '\'))

Magic: nomagic

:help 'nomagic' -- просто не го използвайте. Като "very nomagic", но $ е специален символ.

Magic: обобщение

Magic: обобщение

Magic: обобщение

Syntax highlighting

Syntax highlighting

:help syn-define, доста четене. Централните три команди:

Syntax highlighting

:help syn-define, доста четене. Централните три команди:

1
syntax keyword {name} <keyword1> <keyword2> ...

само една дума, и то само такава, чиито символи са във 'iskeyword' настройката.

Syntax highlighting

:help syn-define, доста четене. Централните три команди:

1
syntax keyword {name} <keyword1> <keyword2> ...

само една дума, и то само такава, чиито символи са във 'iskeyword' настройката.

1
syntax match {name} /<regex>/

Регекса може да е ограден в каквито и да е разделители, не само //

Syntax highlighting

:help syn-define, доста четене. Централните три команди:

1
syntax keyword {name} <keyword1> <keyword2> ...

само една дума, и то само такава, чиито символи са във 'iskeyword' настройката.

1
syntax match {name} /<regex>/

Регекса може да е ограден в каквито и да е разделители, не само //

1
syntax region {name} start=/<regex>/ end=/<regex>/

опционално може да се подаде и skip=/<regex>/

Примери от документацията:

Примери от документацията:

Примери от документацията:

Примери от $VIMRUNTIME/syntax/javascript.vim

1 2 3 4 5 6
syntax keyword javaScriptCommentTodo TODO FIXME XXX TBD contained

syntax match javaScriptLineComment "\/\/.*" contains=@Spell,javaScriptCommentTodo
syntax region javaScriptComment start="/\*" end="\*/" contains=@Spell,javaScriptCommentTodo

syntax region javaScriptEmbed start=+${+ end=+}+ contains=@javaScriptEmbededExpr

Syntax debugging: synID

Синтактичната група под курсора:

1 2 3 4 5
let syn_id = synID(line('.'), col('.'), 0)
" (последния аргумент може да е 1, ако искаме да игнорираме прозрачни групи)

let syn_name = synIDattr(syn_id, "name")
" Примерно: vimComment

Syntax debugging: synID

Синтактичната група под курсора:

1 2 3 4 5
let syn_id = synID(line('.'), col('.'), 0)
" (последния аргумент може да е 1, ако искаме да игнорираме прозрачни групи)

let syn_name = synIDattr(syn_id, "name")
" Примерно: vimComment

Всички stack-нати групи на курсора:

1 2 3 4 5 6
let syn_ids = synstack(line('.'), col('.'))
let syn_names = mapnew(syn_ids, {_, id -> synIDattr(id, "name") })
" { x, y -> ... } -- анонимна функция, която приема два параметъра, x и y

" Това също работи;
let syn_names = mapnew(syn_ids, 'synIDattr(v:val, "name")')

Syncing

Откъде се почва да се highlight-ва?

Syncing

Откъде се почва да се highlight-ва?

Syncing

Откъде се почва да се highlight-ва?

Syncing

Откъде се почва да се highlight-ва?

Syncing

Откъде се почва да се highlight-ва?

Syncing

Откъде се почва да се highlight-ва?

Highlighting

Просто връзваме filetype-специфичните групи с "глобалните":

1 2 3 4 5
highlight link javaScriptComment Comment
" За кратко:
hi link javaScriptComment Comment
" Ако някой реши да линкне *преди* това:
hi default link javaScriptComment Comment

Списък на всички стандартни групи, които не са filetype-specific: :help highlight-groups. Стандартните конвенции като "Comment", "String" etc се гледат от някоя цветова схема.

Повече на следващата лекция.

Highlighting: Images

Няма магия, просто усърдие: https://github.com/tpope/vim-afterimage

Substitute

Виждали сме го и преди: :s/{pattern}/{string}/[flags]

Substitute

Виждали сме го и преди: :s/{pattern}/{string}/[flags]

Substitute

Виждали сме го и преди: :s/{pattern}/{string}/[flags]

Substitute: Backreferences

Разменяме първата и втората capture-ната група:

1
%s/"\(.*\)" => "\(.*\)"/\2 => \1/g

Substitute: Backreferences

Uppercase-ваме стойността в кавичките:

1
%s/=> "\zs.*\ze"/\=toupper(submatch(0))/g

Substitute: Backreferences

Uppercase-ваме стойността в кавичките:

1
%s/=> "\zs.*\ze"/\=toupper(submatch(0))/g
1
%s/=> "\zs.*\ze"/\U\0/g

също работи без expression register -- :help sub-replace-special

Substitute: Backreferences

Разбива реда -- не \n

1
%s/=> ".*"/\r\0/g

Substitute: Трикове

Substitute: Трикове

Global

1
g/<pattern>/<cmd>

"Командата" е каквато и да е команда в нормален режим. Забележете че за разлика от :substitute, без аргументи се прилага върху целия файл (затова е "global"). Но пак приема range.

Често се използва "p", кратко от "print"

Global

1
g/<pattern>/<cmd>

"Командата" е каквато и да е команда в нормален режим. Забележете че за разлика от :substitute, без аргументи се прилага върху целия файл (затова е "global"). Но пак приема range.

Често се използва "p", кратко от "print"

Global

1
g/<pattern>/<cmd>

"Командата" е каквато и да е команда в нормален режим. Забележете че за разлика от :substitute, без аргументи се прилага върху целия файл (затова е "global"). Но пак приема range.

Често се използва "p", кратко от "print"

Global

1
g/<pattern>/<cmd>

"Командата" е каквато и да е команда в нормален режим. Забележете че за разлика от :substitute, без аргументи се прилага върху целия файл (затова е "global"). Но пак приема range.

Често се използва "p", кратко от "print"

Как да упражнявате регекси?

Как да упражнявате регекси?

Как да упражнявате регекси?

Как да упражнявате регекси?

Как да упражнявате регекси?

Въпроси