TCL exec с переменной строкой arg, начинающейся со специальных символов, таких как <,> или | - PullRequest
1 голос
/ 05 марта 2019

Я пытаюсь exec из tcl, передавая переменную, которая может начинаться с <, (или | или >) в качестве аргумента. Кажется, tcl думает, что я хочу направить ввод файла в команду, а не использовать буквенную угловую скобку.

set cmd "<hi>"
exec echo $cmd                # couldn't read file "hi>"
eval exec [list echo $cmd]    # couldn't execute "echo <hi>"
eval exec {*}[list echo $cmd] # couldn't read file "hi>"

Я даже не могу получить ожидаемое <hi> при жестком кодировании строки

eval exec {*}{"echo" <hi>}   # couldn't read file "hi>"
exec echo {"<hi>"}           # "<hi>"  # but I don't want quotes
exec echo {\<hi>}            # \<hi>   # nor a leading \
exec echo {<hi>}             # couldn't read file "hi>"
exec echo {*}[list "<hi>"]   # '
eval exec echo [list "<hi>"] # '

Это похоже на TCL exec со специальными символами в списке , но < отбрасывает решения там

Также, возможно, стоит отметить

1) наличие дополнительных аргументов позволяет | пройти, но не <

eval exec {*}[list echo {|foo bar} ] # |foo bar  # WORKS? WHAT?
eval exec {*}[list echo {|foo} ]     # illegal use of | or |& in command
eval exec {*}[list echo {<foo bar} ] # couldn't read file "foo"

2) дополнительных пробелов или символов достаточно, чтобы обойти проблему (но как использовать их с предоставленной пользователем / проанализированной переменной)

exec echo { <hi>}               #  <hi>    # with leading space
exec echo { |hi}                #  |hi     # with leading space
exec echo [list " " $cmd]       # { } <hi> # not useful
exec echo {*}[list " " $cmd]    #            couldn't read file "hi>"
exec echo [join [list "" $cmd]] #  <hi>    # leading space

exec echo [string trim [join [list "" $cmd]]] # couldn't read file "hi>"

Ответы [ 2 ]

1 голос
/ 05 марта 2019

Один из способов обойти это (немного украсть у @jerry) - записать команду во временный файл и запустить ее с помощью оболочки

   set f [file tempfile fn "/tmp/cmd"]
   # open $fn w # unnecessary
   puts $f $cmd
   close $f
   set shcmd "echo \"`cat $fn`\""
   exec sh -c $shcmd 
   file delete $fn
1 голос
/ 05 марта 2019

Я не очень хорошо разбираюсь в том, что вы пытаетесь сделать, но с некоторыми поисками я нашел этот пост (и так как это не совсем работало ...) и этот пост . Вместе кажется, что работает следующее:

% exec bash -c {echo "<hi>"}
<hi>

Цитирование Колина по первой ссылке:

Exec Tcl не вызывает bash и не выполняет это преобразование самостоятельно. Вы можете заставить его работать, явно вызвав bash из Tcl

...