Реализация "quotemeta" \Q ... \E в Tcl?
Типичный случай использования - когда регулярное выражение должно включать пользовательский ввод. Символы со специальным значением в регулярном выражении (то есть "грязная дюжина" в Perl) должны быть экранированы. Perl предоставляет функциональность "quotemeta" для этого: просто инкапсулируйте интерполяционные переменные в \Q
а также \E
, Но Tcl не предоставляет такой функциональности (и согласно этой странице, даже с ARE).
Есть ли хорошая (строгая) реализация quotemeta в Tcl?
2 ответа
В Perl quotemeta
функция просто заменяет каждый несловарный символ (т. е. символы, отличные от 26 строчных букв, 26 заглавных букв, 10 цифр и подчеркивания), с обратной косой чертой. Это излишне, поскольку не все несловарные символы являются метасимволами регулярного выражения, но это просто и безопасно, поскольку экранирование несловесного символа, которое не требует экранирования, безвредно.
Я считаю, что эта реализация верна:
proc quotemeta {str} {
regsub -all -- {[^a-zA-Z0-9_]} $str {\\&} str
return $str
}
Но благодаря комментарию Гленна, этот лучше, по крайней мере для современных версий Tcl (\W
соответствует любому несловесному символу, начинающемуся через некоторое время после Tcl 8.0.5):
proc quotemeta {str} {
regsub -all -- {\W} $str {\\&} str
return $str
}
(Я предполагаю, что регулярные выражения Tcl достаточно похожи на Perl, поэтому в Tcl они будут выполнять ту же работу, что и в Perl.)
Я предложу решение, но я не уверен, что оно правильное.
#
# notes
#
# - "[]" has to appear in the beginning of a character class
# - "-" has to come last in a character class
# - "#" is not special, but anticipating the x modifier...
# - "-" is not special, but anticipating interpolation within "[]"...
# - "/" is not special in Tcl
#
proc quotemeta {str} {
regsub -all -- {[][#$^*()+{}\|.?-]} $str {\\\0} str
return $str
}