Передача аргументов в tclsh через bash heredoc

У меня есть следующий тестовый пример:

#!/bin/bash
tclsh <<EOF
puts "argv=$argv"
EOF

Как я могу передать аргументы в tclsh? Аргументы должны быть после файла (согласно справочной странице tclsh)

SYNOPSIS
    tclsh ?-encoding name? ?fileName arg arg ...?

Обновлять:

Сначала я возьму флаги команды bash и использую их для создания аргументов для tclsh:

tclarg1="....."
tclarg2="....."

Тогда у меня будет строковая переменная с tcl:

SCRIPT='
    proc test{arg1 arg2} {
        some tcl commands
    }
    test ???? ????
'

И, наконец, я выполняю эту строку:

tclsh <<-HERE
${POPUPSCRIPT}
HERE

Как передать «tclarg1» и «tclarg2» в сценарий tcl?

Строка может быть получена из других источников (путем поиска другого файла), а также сценарий bash может выполнять эту строку из нескольких мест/функций.


person Michael    schedule 23.11.2017    source источник


Ответы (3)


Heredocs отправляются на стандартный ввод программы, поэтому ваша команда:

tclsh <<EOF
puts "argv=$argv"
EOF

вызывает tclsh без аргументов, даже без имени файла, и записывает puts "argv=" в стандартный ввод tclsh. (Обратите внимание, что $argv обрабатывается Bash, поэтому tclsh никогда его не видит. Чтобы это исправить, вам нужно написать <<'EOF' вместо <<EOF.)

Итак, чтобы передать аргументы вашему сценарию tclsh, вам нужно передать tclsh аргумент имени файла, чтобы ваши аргументы могли идти после этого аргумента имени файла.

Так как heredocs отправляются на стандартный ввод программы, используемое имя файла будет просто /dev/stdin:

tclsh /dev/stdin "$tclarg1" "$tclarg2" <<'EOF'
puts "argv=$argv"
EOF

Обратите внимание, что при таком подходе tclsh больше не будет неявно запускать ваш .tclshrc в начале вашего скрипта (поскольку он делает это только тогда, когда он по умолчанию читает из стандартного ввода из-за отсутствия каких-либо аргументов) . Если вам нужно что-то из вашего .tclshrc, вам нужно явно source это:

tclsh /dev/stdin "$tclarg1" "$tclarg2" <<'EOF'
source ~/.tclshrc
puts "argv=$argv"
EOF
person ruakh    schedule 10.06.2019

Это каверзный маленький вопрос, потому что heredocs придирчивы к тому, где они появляются в командной строке. Кроме того, в конечном итоге они передаются командам в виде файловых дескрипторов, поэтому требуется небольшая хитрость.

#!/bin/bash

# Get the script into a variable. Note the backticks and the single quotes around EOF
script=`cat <<'EOF'
puts "argv=$argv"
EOF`

# Supply the script to tclsh as a file descriptor in the right place in the command line
tclsh <(echo $script) "$@"

Кажется, это правильно.

bash$ /tmp/testArgPassing.sh a 'b c' d
argv=a {b c} d

Тем не менее, я бы определенно всегда использовал отдельный файл .tcl в том месте, где в противном случае можно было бы подумать о подобных вещах. Обработка аргументов в Tcl не менее проста, чем в Bash, и это позволяет различным редакторам также обеспечивать разумную подсветку синтаксиса.

А найти правильный tclsh на PATH легко с помощью /usr/bin/env:

#!/usr/bin/env tclsh
puts "argv=$argv"
person Donal Fellows    schedule 10.06.2019

person    schedule
comment
Я не хочу передавать все аргументы в tclsh. Мне нужно подготовить отдельный набор аргументов, созданный в сценарии bash. - person Michael; 05.12.2017
comment
Можете ли вы рассказать о прецеденте и чего вы пытаетесь достичь? - person Sharad; 05.12.2017