Реализация "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
}
Другие вопросы по тегам