tcl
Регулярные выражения
Поиск…
Синтаксис
- regexp? переключатели? exp string? matchVar? ? subMatchVar subMatchVar ...?
- regsub? переключатели? exp string subSpec? varName?
замечания
Эта тема не предназначена для обсуждения самих регулярных выражений. В Интернете много ресурсов, объясняющих регулярные выражения и инструменты, которые помогают создавать регулярные выражения.
В этом разделе будут рассмотрены общие переключатели и методы использования регулярных выражений в Tcl и некоторые различия между Tcl и другими механизмами регулярных выражений.
Регулярные выражения обычно медленны. Первый вопрос, который вы должны задать, - «Нужно ли мне регулярное выражение?». Только соответствует тому, что вы хотите. Если вам не нужны другие данные, не соответствуйте им.
Для целей этих примеров регулярных выражений будет использоваться -расширенный коммутатор, чтобы иметь возможность комментировать и объяснять регулярное выражение.
согласование
Команда regexp используется для сопоставления регулярного выражения с строкой.
# This is a very simplistic e-mail matcher.
# e-mail addresses are extremely complicated to match properly.
# there is no guarantee that this regex will properly match e-mail addresses.
set mydata "send mail to [email protected] please"
regexp -expanded {
\y # word boundary
[^@\s]+ # characters that are not an @ or a space character
@ # a single @ sign
[\w.-]+ # normal characters and dots and dash
\. # a dot character
\w+ # normal characters.
\y # word boundary
} $mydata emailaddr
puts $emailaddr
[email protected]
Команда regexp вернет 1 (истинное) значение, если совпадение было выполнено или 0 (false), если нет.
set mydata "hello wrld, this is Tcl"
# faster would be to use: [string match *world* $mydata]
if { [regexp {world} $mydata] } {
puts "spelling correct"
} else {
puts "typographical error"
}
Чтобы сопоставить все выражения в некоторых данных, используйте ключ -all и ключ -inline для возврата данных. Обратите внимание, что по умолчанию используется обработка новых строк, как и любых других данных.
# simplistic english ordinal word matcher.
set mydata {
This is the first line.
This is the second line.
This is the third line.
This is the fourth line.
}
set mymatches [regexp -all -inline -expanded {
\y # word boundary
\w+ # standard characters
(?:st|nd|rd|th) # ending in st, nd, rd or th
# The ?: operator is used here as we don't
# want to return the match specified inside
# the grouping () operator.
\y # word boundary
} $mydata]
puts $mymatches
first second third fourth
# if the ?: operator was not used, the data returned would be:
first st second nd third rd fourth th
Обработка новой строки
# find real numbers at the end of a line (fake data).
set mydata {
White 0.87 percent saturation.
Specular reflection: 0.995
Blue 0.56 percent saturation.
Specular reflection: 0.421
}
# the -line switch will enable newline matching.
# without -line, the $ would match the end of the data.
set mymatches [regexp -line -all -inline -expanded {
\y # word boundary
\d\.\d+ # a real number
$ # at the end of a line.
} $mydata]
puts $mymatches
0.995 0.421
Unicode не требует специальной обработки.
% set mydata {123ÂÃÄÈ456}
123ÂÃÄÈ456
% regexp {[[:alpha:]]+} $mydata match
1
% puts $match
ÂÃÄÈ
% regexp {\w+} $mydata match
1
% puts $match
123ÂÃÄÈ456
Документация: regexp re_syntax
Смешивание жадных и не жадных квантификаторов
Если у вас есть жадный матч в качестве первого квантификатора, весь RE будет жадным,
Если у вас есть не-жадный матч в качестве первого квантификатора, весь RE будет не жадным.
set mydata {
Device widget1: port: 156 alias: input2
Device widget2: alias: input1
Device widget3: port: 238 alias: processor2
Device widget4: alias: output2
}
regexp {Device\s(\w+):\s(.*?)alias} $mydata alldata devname devdata
puts "$devname $devdata"
widget1 port: 156 alias: input2
regexp {Device\s(.*?):\s(.*?)alias} $mydata alldata devname devdata
puts "$devname $devdata"
widget1 port: 156
В первом случае первая \ w + жадная, поэтому все кванторы отмечены как жадные и. *? соответствует более чем ожидаемому.
Во втором случае первый. *? не является жадным, и все квантификаторы отмечены как не жадные.
Другие механизмы регулярных выражений могут не иметь проблемы с жадными / не жадными кванторами, но они намного медленнее.
Генри Спенсер писал : «Беда в том, что очень сложно написать обобщение тех утверждений, которые охватывают регулярные выражения смешанной жадности - правильное, независимое от реализации определение того, что должно соответствовать регулярным выражениям смешанной жадности - - и заставляет их делать «то, что люди ожидают». Я пробовал. Я все еще пытаюсь. Пока не повезло. ...
подмена
Команда regsub используется для регулярного выражения и подстановки.
set mydata {The yellow dog has the blues.}
# create a new string; only the first match is replaced.
set newdata [regsub {(yellow|blue)} $mydata green]
puts $newdata
The green dog has the blues.
# replace the data in the same string; all matches are replaced
regsub -all {(yellow|blue)} $mydata red mydata
puts $mydata
The red dog has the reds.
# another way to create a new string
regsub {(yellow|blue)} $mydata red mynewdata
puts $mynewdata
The red dog has the blues.
Использование обратных ссылок на сопоставленные данные.
set mydata {The yellow dog has the blues.}
regsub {(yellow)} $mydata {"\1"} mydata
puts $mydata
The "yellow" dog has the blues.
Документация: regsub re_syntax
Различия между двигателем RE Tcl и другими двигателями RE.
- \ m: Начало слова.
- \ M: Конец слова.
- \ y: граница слова.
- \ Y: точка, не являющаяся границей слова.
- \ Z: соответствует концу данных.
Документация: re_syntax
Соответствие строки с регулярным выражением
Иногда вам нужно сопоставить буквенную (суб) строку с регулярным выражением, несмотря на то, что подстрока содержит метасимволы RE. Хотя «да», можно написать код для вставки соответствующих обратных косых черт для выполнения этой работы (с использованием string map ), проще всего просто префикс шаблона с помощью ***= , что заставляет двигатель RE обрабатывать остальную часть строки как буквальные символы , отключая все последующие метасимволы.
set sampleText "This is some text with \[brackets\] in it."
set searchFor {[brackets]}
if {[ regexp ***=$searchFor $sampleText ]} {
# This message will be printed
puts "Found it!"
}
Обратите внимание, что это также означает, что вы не можете использовать ни одного из якорей.