У меня есть скрипт tcl/tk, который я запускаю через wish. Однако я заметил, что некоторые аргументы командной строки передаются в пожелание вместо моего сценария. Например, если я наберу ./script -h, я получу вывод справки по желанию вместо вывода справки по моим сценариям.
Это демонстрирует следующий код, где puts $arvg должен показывать аргументы командной строки. Если я использую аргументы, которые не используются по желанию, например "-i", то они корректно передаются моему скрипту и распечатываются.
#!/usr/bin/env/ wish
puts $argv
Как я могу обеспечить передачу аргументов командной строки моему сценарию, а не интерпретатору?





Для программ с хорошим поведением один из возможных ответов будет таким:
#!/usr/bin/env -S interpreter --
interpreter, что бы это ни было, будет рассматривать -- как аргумент последнего варианта. Затем он будет рассматривать следующий аргумент как имя сценария, а остальные аргументы — как аргументы сценария.
Увы, wish не подчиняется этому соглашению. Хотя он поддерживает --, этот аргумент означает, что «это последний аргумент, который wish обрабатывает сам; все остальное передается сценарию». Аргумент после -- не обрабатывается как файл сценария для чтения.
В документации для -- сказано, что оставшиеся аргументы передаются сценарию, но я не вижу никакого способа указать, что это за сценарий, если используется опция --, кроме размещения ее перед --.
Лучшим вариантом может быть оболочка-оболочка:
#!/bin/sh
myname=$0
tkscript = "${myname%.sh}.tcl"
exec wish "$tkscript" -- "$@" # Thanks to Donal K. Fellows for exec reminder.
Идея в том, что у вас есть вышеуказанный скрипт под именем, скажем, foo.sh. В том же каталоге, что и foo.sh, есть foo.tcl скрипт: настоящий.
Идея состоит в том, что если приведенный выше скрипт вызывается как /path/to/foo.sh, он вычислит имя соседнего скрипта как /path/to/foo.tcl. Это передается в качестве аргумента wish, затем опция --, чтобы сказать «это последний аргумент, обработанный wish», а затем собственные аргументы скрипта, которые больше не интерпретируются wish, даже если они выглядят как опции wish.
Возможно, вам не нужен суффикс .sh, а просто назовите его именем без суффикса, например foo, и в этом случае назначение tkscript упрощается до:
tkscript = "${myname}.tcl"
Используйте exec wish ..., чтобы не создавать новый процесс; вы просто настраиваете параметры запуска.
@DonalFellows Может быть, настало время, когда оболочки вставляются в устранение хвостового вызова сами; кто может не забыть выполнить последнюю строку?
Патч, который я первоначально предложил для GNU Coreutils env (с работающей реализацией, документацией и тестовыми примерами), справится с этой ситуацией; Я поддержал нотацию {}, чтобы указать, где в аргументах должно быть вставлено имя скрипта.
Оболочки предполагают, что вы пишете то, что имеете в виду. По умолчанию оболочки выполняют пост-обработку результатов ваших вызовов (для таких мелочей, как обнаружение сбоев, информация, которую вы в данном случае выбрасываете), поэтому они не могут просто предположить, что вы намеревались полностью делегировать выполнение. Если вы хотите этого, вам нужно написать exec, чтобы сказать это. Это правило.
Вместо того, чтобы вызывать желание в шебанге (напрямую или через env), вызовите tclsh. Таким образом, вы можете манипулировать $argv, который увидит Tk:
#!/usr/bin/env tclsh
# Copy the command line arguments to a new variable
set arglist $argv
# Turn tclsh into wish without passing the command line options
set argv {}
package require Tk
puts $arglist
Обычно я выполняю всю свою обработку командной строки перед package require Tk. Итак, перед запуском Tk необходимо только очистить argv.
Я удалил свой ответ. Аргумент
--вwishозначает не «это последний аргумент без опций», а «это последний аргумент, имеющий какое-либо значение дляwish». Ой!