TCL regsub использует соответствие RegEx как индекс в ассоциированном массиве

Я хочу автоматически конвертировать URL-адреса, т.е.

Я пробовал следующий фрагмент кода в TCL

set loc "https://sc-uat.ct.example.com/sc/"

set envs(dev) "test"
set envs(uat) "beta"
set envs(qa) "demo"

puts $envs(uat)
regsub -nocase {://.+-(.+).ct.example.com} $loc {://inv[$envs(\1)].example.com} hostname

puts "new location = $hostname"

Но результат: новое местоположение = https://inv%5B$envs(uat)]. Example.com/sc/

Кажется, что [$envs(UAT)] является НЕ оценен и замещенным далее с реальным значением. Любые подсказки будут оценены. заранее спасибо

1 ответ

Но результат такой: новое местоположение = https://inv%5B$envs(uat)]. Example.com/sc/ Похоже, что [$envs(uat)] оценивается дальше.

Вы хотели сказать: [$envs(uat)]это не оценивается дальше?

Это потому, что из-за фигурных скобок в {://inv[$envs(\1)].example.com}, вводимая строка воспринимается буквально и не подвергается подстановке переменных или команд. Кроме того, вам не нужна подстановка команд и переменных ([$envs(\1)]), только один из них: $envs(\1) или [set envs(\1)].

Чтобы преодолеть это, вы должны обработать строку, обработанную regsub, через subst:

set hostname [subst -nocommands -nobackslashes [regsub -nocase {://.+-(.+).ct.example.com} $loc {://inv$envs(\1).example.com}]]

Предложения по улучшению

Советую избегать использования substв этом контексте, поскольку даже при ограничении вы можете столкнуться с конфликтами со специальными для Tcl символами в ваших именах хостов (например, скобками в частях полномочий IPv6). Либо надо продезинфицироватьloc строка до или, лучше работать с диапазонами строк, например:

if {[regexp -indices {://(.+-(.+)).ct.example.com} $loc _ replaceRange keyRange]} {
    set key [string range $loc {*}$keyRange]
    set sub [string cat "inv" $envs($key)]
    set hostname [string replace $loc {*}$replaceRange $sub]
}
Другие вопросы по тегам