TCL regsub использует соответствие RegEx как индекс в ассоциированном массиве
Я хочу автоматически конвертировать URL-адреса, т.е.
- " https://sc-uat.ct.example.com/sc/" на " https://invbeta.example.com/sc/"
- " https://sc-dev.ct.example.com/sc/" на " https://invtest.example.com/sc/"
- " https://sc-qa.ct.example.com/sc/" на " https://invdemo.example.com/sc/"
Я пробовал следующий фрагмент кода в 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]
}