В какой степени другие POSIX-совместимые оболочки могут служить разумной заменой bash? Они не должны быть настоящими «заменами», но достаточно близки, чтобы работать с большинством сценариев и поддерживать остальные с некоторыми изменениями.
Я хочу, чтобы явные сценарии bash - initscripts, сценарии DHCP-клиента и т. Д. - работали с минимальными изменениями
Я хочу, чтобы моя собственная коллекция более специализированных сценариев оболочки не требовала особых изменений
Я хочу иметь такие функции, как манипуляции со строками и встроенное сопоставление с регулярным выражением
Единственные серьезные соперники, о которых я знаю, это zsh и mksh. Итак, для тех из вас, кто хорошо с одним или обоими из них:
Какие функции есть у bash, чего нет у zsh и mksh соответственно?
Какими функциями оболочки делятся с bash, но используют несовместимый синтаксис?
bash
, mksh и zsh могут функционировать как/bin/sh
с различными уровнями корректности, но нетbash
.Ответы:
Я буду придерживаться скриптовых функций. Богатые интерактивные функции (редактирование командной строки, завершение, подсказки и т. Д.), Как правило, сильно отличаются друг от друга, достигая аналогичных эффектов совершенно несовместимыми способами. Какие функции есть в zsh и отсутствуют в bash, или наоборот? дает несколько советов по интерактивному использованию.
Наиболее близким к bash будет ATT ksh93 или mksh (оболочка Korn и клон). Zsh также имеет подмножество функций, но вам нужно будет запустить его в режиме эмуляции ksh, а не в собственном режиме zsh.
Я не буду перечислять функции POSIX (которые доступны в любой современной
sh
оболочке), ни относительно неясные функции, ни упомянутые выше функции для интерактивного использования. Наблюдения действительны для bash 4.2, ksh 93u и mksh 40.9.20120630, как указано в Debian wheezy.Синтаксис оболочки
квотирование
$'…'
(буквенные строки с интерполяцией обратной косой черты) доступны в ksh93 и mksh. `$"… "(Переведенные строки) зависит от bash.Условные конструкции
Mksh и ksh93 должны
;&
провалиться вcase
утверждении, но не;;&
для проверки последующих случаев. Для этого есть Mksh;|
, а недавний mksh обеспечивает;;&
совместимость.((…))
арифметические выражения и[[ … ]]
тесты являются особенностями ksh. Некоторые условные операторы разные, см. «Условные выражения» ниже.Coprocesses
Ksh и bash оба имеют сопроцессы, но работают по-разному.
функции
Mksh и ksh93 поддерживают
function name {…}
синтаксис для определений функций в дополнение к стандартуname () {…}
, но использованиеfunction
в ksh изменяет правила области видимости, так что придерживайтесьname () …
для поддержания совместимости. Правила для разрешенных символов в именах функций различаются; придерживаться буквенно-цифровых символов и_
.Расширение скобки
Ksh93 и mksh поддерживают расширение скобки
{foo,bar}
. Ksh93 поддерживает числовые диапазоны,{1..42}
а mksh - нет.Расширение параметра
Ksh93 и mksh поддерживают извлечение подстрок с помощью
${VAR:offset}
и${VAR:offset:length}
, но не сворачивание, как${VAR^}
,${VAR,}
и т. Д. Вы можете выполнить преобразование с помощьюtypeset -l
иtypeset -u
в bash, и в ksh.Они поддерживают замену на
${VAR/PATTERN/STRING}
или${VAR/PATTERN//STRING}
. Правила цитирования для STRING немного отличаются, поэтому избегайте обратной косой черты (и, возможно, других символов) в STRING (создайте переменную и используйте${VAR/PATTERN/$REPLACEMENT}
вместо нее, если замена содержит символы цитирования).Расширение Array (
${ARRAY[KEY]}
,"${ARRAY[@]}"
,${#ARRAY[@]}
,${!ARRAY[@]}
) работа в Баш как в KSH.${!VAR}
расширение до того,${OTHERVAR}
когда значениеVAR
isOTHERVAR
(косвенная ссылка на переменную) зависит от bash (ksh делает что-то другое с${!VAR}
). Чтобы получить это двойное расширение в ksh, вам нужно использовать ссылку на имя вместо (typeset -n VAR=OTHERVAR; echo "$VAR"
).${!PREFIX*}
работает так же.Процесс замещения
Подстановка процесса
<(…)
и>(…)
поддерживается в ksh93, но не в mksh.Шаблоны подстановочных знаков
Шаблоны расширенного глобуса ksh, которые необходимо
shopt -s extglob
активировать в bash, всегда доступны в ksh93 и mksh.Mksh не поддерживает классы символов, такие как
[[:alpha:]]
.Перенаправление ввода / вывода
Bash и ksh93 определяют псевдо-файлы и , но МКШ не делает.
/dev/tcp/HOST/PORT
/dev/udp/HOST/PORT
Расширение подстановочных знаков в перенаправлении в сценариях (как при
var="*.txt"; echo hello >$a
записи,a.txt
если это имя файла является единственным совпадением для шаблона) является специфической функцией bash (другие оболочки никогда не делают это в сценариях).<<<
здесь строки работают в ksh как в bash.Ярлык
>&
для перенаправления синтаксических ошибок также поддерживается mksh, но не ksh93.Условные выражения
[[ … ]]
синтаксис двойных скобокСинтаксис двойной скобки из ksh поддерживается как ATT ksh93, так и mksh, как в bash.
Файловые операторы
Ksh93, mksh и bash поддерживают одинаковые расширения POSIX, в том числе
-a
как устаревший синоним-e
,-k
(sticky),-G
(принадлежит egid),-O
(владелец euid),-ef
(тот же файл),-nt
(новее чем),-ot
(старше чем).-N FILE
(изменено с момента последнего чтения) не поддерживается mksh.Mksh не имеет оператора соответствия регулярному выражению
=~
. В Ksh93 есть этот оператор, и он выполняет то же сопоставление, что и в bash, но не имеет эквивалентаBASH_REMATCH
для извлечения соответствующих групп впоследствии.Строковые операторы
Ksh93 и mksh поддерживают одинаковые операторы сравнения строк
<
и>
как bash, так и==
синоним=
. Mksh не использует настройки локали для определения лексикографического порядка, он сравнивает строки как строки байтов.Другие операторы
-v VAR
проверить, определена ли переменная, зависит от bash. В любой оболочке POSIX вы можете использовать[ -z "${VAR+1}" ]
.Встроенные команды
alias
Набор разрешенных символов в псевдонимах не одинаков во всех оболочках. Я думаю, что это так же, как для функций (см. Выше).
builtin
Ksh93 имеет встроенную функцию
builtin
, но она не выполняет имя как встроенную команду. Используйтеcommand
для обхода псевдонимов и функций; это вызовет встроенную функцию, если она существует, в противном случае - внешнюю команду (вы можете избежать этого с помощьюPATH= command error_out_if_this_is_not_a_builtin
).caller
Это зависит от bash. Вы можете получить аналогичный эффект с
.sh.fun
,.sh.file
и.sh.lineno
в ksh93. В Мкш наконец-то естьLINENO
.declare
,local
,typeset
declare
специфичное для bash имя для kshtypeset
. Использованиеtypeset
: это также работает в Bash.Мкш определяет
local
как псевдоним дляtypeset
. В ksh93 вам нужно использоватьtypeset
(или определить псевдоним).Mksh не имеет ассоциативных массивов (они предназначены для еще не выпущенной версии).
Я не думаю, что есть точный эквивалент bash
typeset -t
(функция трассировки) в ksh.cd
Кш93 не имеет
-e
.echo
Кш93 и мкш обрабатывают
-e
и-n
варианты как в bash. Mksh также понимает-E
, ksh93 не рассматривает это как вариант. Расширение с обратной косой чертой отключено по умолчанию в ksh93, по умолчанию включено в mksh.enable
Ksh не предоставляет способ отключить встроенные команды. Чтобы избежать встроенного, ищите путь внешней команды и вызывайте ее явно.
exec
Кш93 есть
-a
но нет-l
. Мкш не имеет ни того, ни другого.export
Ни ksh93, ни mksh не имеет
export -n
. Используйтеtypeset +x foo
вместо этого, это работает в bash и ksh.Ksh не экспортирует функции через окружение.
let
let
то же самое в bash и ksh.mapfile
,readarray
Это особенность bash. Вы можете использовать
while read
циклы или подстановку команд, чтобы прочитать файл и разбить его на массив строк. Позаботьтесь о себеIFS
и окунитесь. Вот эквивалентmapfile -t lines </path/to/file
:printf
printf
очень похожа. Я думаю, что ksh93 поддерживает все директивы формата bash. mksh не поддерживает%q
или%(DATE_FORMAT)T
; на некоторых установкахprintf
не является встроенным mksh и вместо этого вызывает внешнюю команду.printf -v VAR
специфичен для bash, ksh всегда печатает на стандартный вывод.read
Несколько опций зависят от bash, включая все о readline. Варианты
-r
,-d
,-n
,-N
,-t
,-u
идентичны в Баш, ksh93 и МКШ.readonly
Вы можете объявить переменную только для чтения в Ksh93 и mksh с одинаковым синтаксисом. Если переменная является массивом, вам нужно сначала присвоить ее, а затем сделать ее доступной только для чтения
readonly VAR
. Функции нельзя сделать доступными только для чтения в ksh.set
,shopt
Все опции
set
иset -o
являются функциями POSIX или ksh.shopt
является специфичным для bash. В любом случае многие варианты касаются интерактивного использования. Влияние на глобализацию и другие функции, включенные некоторыми опциями, см. В разделе «Опции» ниже.source
Этот вариант
.
существует и в ksh. В bash и mkshsource
ищет текущий каталог послеPATH
, но в ksh93 это точный эквивалент.
.trap
DEBUG
Псевдо-сигнал не реализован в МКШ. В ksh93 он существует с другим способом сообщения информации, подробности см. В руководстве.type
В ksh
type
это псевдоним дляwhence -v
. В mkshtype -p
не печатает путь к исполняемому файлу, а читаемое человеком сообщение; Вы должны использоватьwhence -p COMMAND
вместо этого.Опции
shopt -s dotglob
- не игнорируйте точечные файлы в globbingЧтобы эмулировать
dotglob
опцию в ksh93, вы можете установитьFIGNORE='@(.|..)'
. Я не думаю, что есть что-то подобное в mksh.shopt -s extglob
- ksh расширенные шаблоны глобусаЭта
extglob
опция всегда включена в ksh.shopt -s failglob
- ошибка, если шаблон глобуса ничего не соответствуетЯ не думаю, что это существует в mksh или ksh93. Это делается в Zsh (поведение по умолчанию, если
null_glob
илиcsh_null_glob
не установлены).shopt -s globstar
-**/
рекурсивное смазываниеKsh93 имеет рекурсивное сглаживание с
**/
включенным сset -G
. У Мкша нет рекурсивных шаров.shopt -s lastpipe
- выполнить последнюю команду конвейера в родительской оболочкеKsh93 всегда запускает последнюю команду конвейера в родительской оболочке, которая в bash требует установки
lastpipe
опции. Mksh всегда запускает последнюю команду конвейера в подоболочке.shopt -s nocaseglob
,shopt -s nocasematch
- модель без учета регистраУ Mksh нет сопоставления с регистром без учета регистра. Ksh93 поддерживает его на основе паттернов: паттерн с префиксом
~(i)
.shopt -s nullglob
- развернуть шаблоны, которые не соответствуют ни одному файлу, в пустой списокУ Мкша этого нет. Ksh93 поддерживает его на основе паттернов: паттерн с префиксом
~(N)
.переменные
Очевидно, что большинство
BASH_xxx
переменных не существует в ksh.$BASHPID
может эмулироваться с дорогостоящим, но переносимымsh -c 'echo $PPID'
, и недавно был добавлен в mksh.BASH_LINE
есть.sh.lineno
в кш93 иLINENO
в мкш.BASH_SUBSHELL
находится.sh.subshell
в кш93.Mksh и ksh93 оба получают файл, указанный
ENV
при запуске.EUID
иUID
не существует в ksh93. Мкш называет ихUSER_ID
иKSH_UID
; это не имеетGROUPS
.FUNCNAME
иFUNCNEST
не существует в кш. Кш93 имеет.sh.fun
и.sh.level
. Функции, объявленные сfunction foo { …; }
(без скобок!), Имеют собственное имя в$0
.GLOBIGNORE
существует в ksh93, но с другим именем и синтаксисом: он называетсяFIGNORE
, и это один шаблон, а не разделенный двоеточиями список. Используйте@(…|…)
шаблон. Ksh включает вFIGNORE
себя bash с совершенно другим синтаксисом.Ksh93 и МКШ не имеют ничего подобного
HOSTTYPE
,MACHTYPE
иOSTYPE
. НиSHELLOPTS
илиTIMEFORMAT
.Мкш имеет
PIPESTATUS
, но ksh93 нет.Мкш и кш93 есть
RANDOM
.источник
$BASHPID
подражатьsh -c 'echo $PPID'
? Я пробовал(sh -c 'echo $PPID')
в Bash, но он дает мне тот же PID, что и$$
.Этот вопрос слишком широкий.
И mksh, и zsh являются оболочками, которые поддерживают множество специфичных для GNU bash расширений, но всегда есть некоторые, которые не поняты.
zsh поддерживает больше вещей, но только в собственном режиме zsh, который не совместим с оболочками POSIX (такими как GNU bash, AT & T ksh93 , mksh). Кроме того, MKSH гораздо более тонкий и быстрый и более портативный.
В общем, если речь идет о ваших сценариях, просто протестируйте их. (mksh пока не поддерживает ассоциативные массивы в стиле bash4. Команда «Declare» является специфичной для bash, «typeset» является эквивалентом. Я не достаточно знаком с zsh, чтобы что-то прямо сказать об этом. ksh93 не имеет «local» но для этого также используется «typeset».) Но если речь идет, скажем, о запуске системы Debian без bash, забудьте об этом. Существование bash является частью «обещания» (API / ABI системы) и во многом зависит от него.
Отказ от ответственности: я разработчик MKSH.
источник
ZSH Сравнение оболочек
Я больше всего незнаком с mksh, поэтому не знаю, где искать этот ответ.
Если вы ищете безопасную замену оболочки, ни одна из этих оболочек не сильно отличается от Bash, поскольку вы обсуждаете врожденный недостаток.
Такой язык, как Perl, обрабатывает ввод более безопасно. Но ремонтопригодность также является ключевой здесь. Замена оболочки Perl не очень хорошо принята. Ответственный за оболочку отвечает за безопасную обработку ввода. Поэтому, когда вы пишете сценарии, проверяйте, проверяйте, проверяйте все! Используйте кодовые контракты, чтобы гарантировать правильные результаты каждый раз!
Perl Shell
Заявление FSF о Шок Шелл
источник
Одной из функций, не включенных по умолчанию,
mksh
является история оболочки.В вашем
.mkshrc
только что установленном:export HISTFILE=~/.mksh-history
источник