echo
— это непереносимая -команда, поведение которой различается в зависимости от реализации, версии, времени компиляции -и параметра времени выполнения, а также среды.
В частности, вы не должны использовать его, если его первый аргумент может начинаться с -
(, хотя встроенная функция zsh echo
является одной из редких реализаций, которые могут обойти это ), или если какой-либо аргумент содержит символы обратной косой черты.
В частности, со встроенной реализациейzsh
echo
\
последовательности (, такие как \n
, \c
, \61
, \\
... ), расширяются (в соответствии с требованиями POSIX. +XSI, в то время как POSIX без XSI оставляет поведение неопределенным ), если опция bsdecho
не включена (отключена по умолчанию в большинстве развертываний ), а для bash
они расширяются только тогда, когда xpg_echo
включено (отключено по умолчанию в большинстве развертываний ).
И zsh
, иbash
echo
поддерживают (нестандартную -опцию)-E
для отключения расширений (, не поддерживаемых bash
, если и xpg_echo
, и posix
] параметры включены, хотя ).
Здесь, хотя вы могли бы сделать:
echo -E '\\' > file
Что будет нормально работать в zsh
и в большинстве развертываний bash
, было бы гораздо лучше использовать стандартную команду printf
:
printf '%s\n' '\\' > file
Чье поведение в этом случае полностью определяется POSIX и работает одинаково во всех реализациях.
Обратите внимание, что утилита printf
является изобретением POSIX. Задолго до POSIX ответом оболочки Korn на эту не -переносимую echo
путаницу -была новая print
встроенная функция с ее -r
возможностью не расширять \x
последовательности и -
для пометки конец вариантов. zsh
имеет встроенный Korn -, подобный print
, а bash
— нет.
В кш и зш тоже можно сделать:
print -r - "$var"
Для печати произвольных данных, как -.
Подробнее на:
Использование вами getopts :rt:
сообщает оболочке, что вам требуется аргумент для опции "t".
На справочной странице getopts:
[...] if a character is followed by a colon, the option is expected to have an argument, which should be separated from it by white space [...] When an option requires an argument, getopts places that argument into the variable OPTARG
Если вы хотите сделать аргумент для -t необязательным, вам нужно удалить двоеточие и обработать следующий аргумент вручную:
while getopts :rt option
do
case "${option}" in
r)
REST=true
#echo "Restart"
;;
t)
TIMEOFDAY=${!OPTIND}
TIME=true
case "$TIMEOFDAY" in
n | d)
echo "$TIMEOFDAY"
;;
"")
echo "-t argument requires an option."
exit 2
;;
*)
echo "Invalid argument for -t, use only 'd' or 'n'"
exit 0
;;
esac
;;
*)
echo "Argument -${OPTARG} not found."
echo "Use only -r and -t."
exit 0
;;
esac
done
В вашем коде два изменения:
:rt:
на :rt
сообщает getopts, что опция "t" не требует указания аргумента. TIMEOFDAY=${OPTARG}
на TIMEOFDAY=${!OPTIND}
. Снова из справочной страницы:
Each time it is invoked, the getopts utility shall place the value of the next option in the shell variable specified by the name operand and the index of the next argument to be processed in the shell variable OPTIND.
Таким образом, при обработке опции "t" переменная OPTIND будет иметь порядковый номер следующей опции . Синтаксис ${! переменная } косвенно ссылается на значение переменной .
Я повторно -создал его в песочнице и добавил еще одну строку, повторяющую значение OPTIND, чтобы объяснить его здесь:Попробуйте онлайн!