Переменная подсказки (t )csh — $prompt
[1], поэтому прямой ответ на ваш вопрос —:
printf '%s\n' "$prompt"
В tcsh
(, но не в оригинальном csh
), вы можете использовать побег %t
для времени в формате 12 часов утра/вечера:
% set prompt = "%t - $prompt"
1:53pm - % _
или %P
для 24-часового формата с секундами:
% set prompt = "$prompt (%P) "
% (13:55:31) _
Вы можете увидеть полный список escape-последовательностей на tcsh (1)справочной странице.
[1] tcsh
также имеет $prompt2
для циклов foreach
/ while
и продолжения строки \
и $prompt3
для функции исправления орфографии.
Форма ${ cmds;}
подстановки команд ksh93 работает cmds
в той же оболочке, но в остальном захватывает стандартный вывод, как обычная подстановка команд. Пример:
a=1; echo ${ a=2; echo wtf;}; echo $a
wtf
2
И тот факт, что он захватывает стандартный вывод команд, именно делает его полезным, поскольку вам не нужно сохранять вывод во временный файл, а затем читать его или настраивать именованный канал или перепишите какую-нибудь мохнатую функцию, чтобы она добавляла свой вывод к какой-либо переменной, а не просто записывала ее.
И это очень сильно отличается от функции "подстановки значений" mksh, для которой я не могу найти никакого объяснения. Почему нельзя присвоить переменную REPLY
раньше, а затем просто использовать ее как $REPLY
?
Чтобы ответить на вопрос, который на самом деле задан :Нет. В других оболочках такого нет.
Как сообщает нам журнал изменений оболочки MirBSD Korn, замены значений были добавлены Томасом Гойраном в 2014 году к выпуску 46.
Насколько мне известно, ни одна другая оболочка не копировала эту идею ни тогда, ни после. У некоторых из них есть то, что подстановки значений были получены из , но на самом деле у них нет подстановок значений.
Эта функция, называемая подстановкой значений или valsub Торстена Глейзера (, также известного как @mirabilos ), производная от сопровождающего или MirBSD и ее оболочки mksh
(. из pdksh ), относится к mksh
.
Он был включен в кодовую базу mksh 2 мая 2013 г. и выпущен в версии R46, объявленной на следующий день в списке рассылки mksh.
Это написано на обратной стороне ${ body; }
формы подстановки команд (, называемой подстановкой функций или funsub в mksh
), скопированной из ksh93 в феврале того же года и также выпущен в R46.
В ksh93 ввод-вывод из встроенных модулей виртуализирован. Ни $(builin-cmd)
, ни ${ builtin-cmd; }
не содержат ответвления или ввода/вывода. Таким образом, $(print foo)
или ${ print foo; }
расширяются до foo
и отвечают вашим требованиям к оператору, не включающему никакого fd.
В обеих формах встроенная команда print
ничего не записывает в какой-либо fd, но ее -будет -вывод (, обрезанный конечными символами новой строки ), составляющий расширение. Разница между ними заключается в том, что $(...)
вводит среду подоболочки (, которая, в отличие от других оболочек, не реализуется путем разветвления дочернего процесса ), а ${...; }
— нет.
Теперь, чтобы сделать это, ksh93 (переписать сам ksh (1983 года )почти с нуля ), все операции ввода-вывода в оболочке должны были быть специально переписаны. Когда mksh добавил эту функцию ${...; }
в 2013 году, он использовал более простой подход, который просто записывает вывод в удаленный временный файл и считывает содержимое этого файла после того, как код в нем возвращается, чтобы составить расширение.
Однако это означает, что выходные данные в конечном итоге сохраняются на диске, даже если они временно, а ввод-вывод означает более низкую производительность, чем если бы результирующие данные просто передавались в память, как в ksh93.Поэтому я предполагаю, что именно поэтому Торстен добавил эту ${|...; }
отдельную форму, которая может передавать значение, используя выделенную переменную ($REPLY
), и опять же не требует серьезной переработки внутренних компонентов оболочки.
Однако это означает, что функции, которые используются таким образом, должны быть написаны специально, чтобы возвращать свое значение в $REPLY
(, которое может быть только скалярным, а не списком, кроме как через split+glob ), и просто становится немного синтаксический сахар. Пример:
sanitize() {
REPLY=${1//[!0123456789-]}
local sign=
case $REPLY in
(-*) REPLY=${REPLY#-}; sign=-
esac
REPLY=$sign${REPLY//-}
}
print "$(( ${|sanitize "$1"} + ${|sanitize "$2"} ))"
Без него пришлось бы писать:
sanitize "$1"; a=$REPLY
sanitize "$2"; b=$REPLY
print "$(( a + b ))"
Одним из преимуществ по сравнению с $(...)
и ${...; }
является то, что он не удаляет завершающие символы новой строки. Например, $(basename -- "$file")
неверен, так как не работает, если $file
заканчивается символами новой строки, в то время как ${|basename -- "$file"}
(, предполагая, что basename
была переписана как функция, возвращающая базовое имя из $REPLY
), не имела бы проблема.
Другие оболочки с конструкциями, которые могут возвращать значения без участия ввода-вывода:
Кто-то предложил реализовать упрощенную версию mksh valsub в 2019 году , которая в конечном итоге превратилась в это предложение , но, насколько мне известно, оно еще не дошло до zsh
.
Однако у zsh есть несколько альтернативных способов расширения, являющихся результатом произвольного кода, без участия подоболочки или ввода-вывода.
Для арифметики zsh
имеет понятие математических функций:
square() (( $1 * $1))
functions -M square 1
echo $(( square(5) + square(12) ))
Это ограничено числами, хотя (целым числом или числом с плавающей запятой )и может использоваться только в арифметических выражениях. Однако сами математические функции могут принимать числа, отличные от -, в качестве аргументов с functions -sM
), поэтому, хотя это и очень запутанно, вы можете сделать:
func() REPLY=foo$1; functions -sM func
echo ${$((func(bar)))+$REPLY} ${$((func(baz)))+$REPLY}
как эквивалент mksh
's:
func() REPLY=foo$1
echo "${|func bar}" "${|func baz}"
zsh
имеет другую форму расширения, чем может быть вычислено с помощью шелл-кода без ввода-вывода.Это использует структуру настройки для расширения тильды под названием Динамические именованные каталоги(см.info zsh dynamic
).
Если вы определяете:
autoload -Uz add-zsh-hook
valsub() {
[[ $1 = n && $2 = '!'* ]] && eval "${2#?}" && reply=("$REPLY")
}
add-zsh-hook -Uz zsh_directory_name valsub
Тогда тильда расширения формы ~[!'REPLY=something']
расширится до something
.
Расширение тильды выполняется не во всех контекстах, но вы также можете использовать эту функцию динамических именованных каталогов как часть расширения параметра, используя прием , описанный в упомянутом выше обсуждении поддержки valsub. .
Подстановочные знаки также могут расширяться до результата произвольного кода с помощьюe
(для оценки)или +
подстановочных знаков.
Они обычно используются для фильтрации файлов на основе результата выполнения некоторого кода.
Нравится:
ls -ld -- *.txt(e['(( $#REPLY > 20 ))'])
Чтобы выбрать имена файлов txt, длина которых превышает 20 символов. Но также может использоваться для изменения результата расширения:
ls -ld -- *.txt(e['REPLY=$REPLY:r.html'])
(расширить до txt
файлов с заменой расширения наhtml
). Или даже:
ls -ld -- *.txt(e['reply+=($REPLY:r.html)'])
Возвращает перевод txt
и html
.
Так что вы действительно можете:
echo /(e['REPLY=foobar'])
Чтобы расширить результат произвольного кода, здесь применяется квалификатор /
, который, как мы знаем, всегда существует. Или даже список:
printf '<%s>\n' /(e['reply=(foo bar)'])
Квалификатор +
— это вариант, который просто принимает имя функции, поэтому вы можете использовать echo /(+func)
, где func
— это функция, которая генерирует расширение.
Опять же, как и для расширения ~
, подстановка выполняется не в каждом контексте.
es
является производным от Байрона Ракитзиса общедоступного клона оболочки Research Unix V10/Plan9 rc
.
rc
могут возвращать список статусов выхода. (может быть именем сигнала или положительными целыми числами. )и предоставляется вызывающей стороне в переменной списка $status
.
es
расширил его, чтобы он мог возвращать любой список чего угодно, и вместо того, чтобы делать его доступным в $status
, статус выхода (или возвращаемое значение функции )получают с синтаксисом <={...}
.
Так что можно сделать:
fn foo { return foo$1 }
echo <={foo bar}
например.
Однако обратите внимание, что только возвращаемое значение из пустого списка или списка, все элементы которого пусты или равны 0, интерпретируется как успешное . Так, например, здесь foo anything && echo bar
никогда не будет выводить bar
, поскольку foo
всегда возвращает значение, которое никогда не интерпретируется как успех .
Помимо уже рассмотренных $(...)
, ${...; }
, существуют функции, которые позволяют расширениям иметь динамическое содержимое без участия ввода-вывода:
Вы можете определить функцию, которая вызывается каждый раз при установке или расширении переменной. Для переменных ассоциативного массива эти функции будут иметь доступ к нижнему индексу, поэтому вы можете использовать его для передачи одного произвольного аргумента в функцию:
typeset -A valsub
function valsub.get {
.sh.value=foo${.sh.subscript}
}
echo "${valsub[bar]}"
будет выводить foobar
.
ksh93 также имеет математические функции, хотя и с другим синтаксисом, чемzsh
:
function.sh.math.square x {((.sh.value = x*x))}
echo "$(( square(5) + square(12) ))"