¿Hasta qué punto pueden funcionar otros shells compatibles con POSIX como reemplazos razonables para bash? No necesitan ser verdaderos reemplazos "directos", pero lo suficientemente cerca como para funcionar con la mayoría de los scripts y admitir el resto con alguna modificación.
Quiero tener scripts de bash explícitos (initscripts, scripts de cliente DHCP, etc.) que funcionen con una modificación mínima
Quiero que mi propia colección de scripts de shell más especializados no necesite demasiada modificación
Quiero tener características como la manipulación de cadenas y la coincidencia de patrones de expresiones regulares incorporadas
Los únicos contendientes serios que conozco son zsh y mksh. Entonces, para aquellos de ustedes aquí que son buenos con uno o ambos:
¿Qué características tiene bash que zsh y mksh respectivamente no tienen?
¿Qué características comparten los shells con bash, pero usan una sintaxis incompatible?

bash, mksh y zsh puede funcionar como/bin/shcon varios niveles de corrección, pero nobash.Respuestas:
Me atendré a las funciones de secuencias de comandos. Las características interactivas ricas (edición de línea de comandos, finalización, indicaciones, etc.) tienden a ser muy diferentes, logrando efectos similares de maneras totalmente incompatibles. ¿Qué características están en zsh y faltan en bash, o viceversa? da algunos consejos sobre el uso interactivo.
Lo más parecido a bash sería ATT ksh93 o mksh (el shell Korn y un clon). Zsh también tiene un subconjunto de características, pero necesitaría ejecutarlo en modo de emulación ksh, no en modo nativo de zsh.
No enumeraré las características de POSIX (que están disponibles en cualquier
shshell moderno ), ni las características relativamente oscuras, ni las características mencionadas anteriormente para uso interactivo. Las observaciones son válidas a partir de bash 4.2, ksh 93u y mksh 40.9.20120630 como se encuentra en Debian wheezy.Sintaxis de Shell
Citando
$'…'(cadenas literales con interpolación de barra invertida) está disponible en ksh93 y mksh. `$" ... "(cadenas traducidas) es específico de bash.Construcciones condicionales
Mksh y ksh93 tienen que fallar
;&en unacasedeclaración, pero no;;¶ probar casos posteriores. Mksh tiene;|para eso, y mksh reciente permite;;&compatibilidad.((…))Las expresiones y[[ … ]]pruebas aritméticas son características de ksh. Algunos operadores condicionales son diferentes, consulte "expresiones condicionales" a continuación.Coprocesos
Ksh y bash tienen coprocesos pero funcionan de manera diferente.
Las funciones
Mksh y ksh93 admiten la
function name {…}sintaxis de las definiciones de funciones además del estándarname () {…}, pero el usofunctionde ksh cambia las reglas de alcance, por lo quename () …debe mantener la compatibilidad. Las reglas para los caracteres permitidos en los nombres de funciones varían; atenerse a los caracteres alfanuméricos y_.Expansión de la llave
Ksh93 y mksh admiten la expansión de llaves
{foo,bar}. Ksh93 admite rangos numéricos{1..42}pero mksh no.Expansión de parámetros
Ksh93 y apoyo extracción mksh subcadena con
${VAR:offset}y${VAR:offset:length}, pero no como el caso plegable${VAR^},${VAR,}, etc Usted puede hacer la conversión casotypeset -lytypeset -utanto en bash y ksh.Admiten el reemplazo con
${VAR/PATTERN/STRING}o${VAR/PATTERN//STRING}. Las reglas de comillas para STRING son ligeramente diferentes, por lo tanto, evite las barras invertidas (y tal vez otros caracteres) en STRING (cree una variable y${VAR/PATTERN/$REPLACEMENT}úsela si el reemplazo contiene caracteres de comillas).Expansión Array (
${ARRAY[KEY]},"${ARRAY[@]}",${#ARRAY[@]},${!ARRAY[@]}) de trabajo en bash como en ksh.${!VAR}expandiéndose a${OTHERVAR}cuando el valor deVARisOTHERVAR(referencia de variable indirecta) es específico de bash (ksh hace algo diferente con${!VAR}). Para obtener esta doble expansión en ksh, debe usar una referencia de nombre en su lugar (typeset -n VAR=OTHERVAR; echo "$VAR").${!PREFIX*}funciona igualProceso de sustitución
Proceso de sustitución
<(…)y>(…)se admite en ksh93 pero no en mksh.Patrones comodín
Los patrones de globo extendido ksh que deben
shopt -s extglobactivarse en bash siempre están disponibles en ksh93 y mksh.Mksh no admite clases de personajes como
[[:alpha:]].Redirección de IO
Bash y ksh93 definen pseudo-archivos y , pero mksh no.
/dev/tcp/HOST/PORT/dev/udp/HOST/PORTLa expansión de comodines en una redirección en los scripts (como por
var="*.txt"; echo hello >$aescritoa.txtsi ese nombre de archivo es la única coincidencia para el patrón) es una característica específica de bash (otros shells nunca lo hacen en scripts).<<<Las cadenas aquí funcionan en ksh como en bash.El acceso directo
>¶ redirigir errores de sintaxis también es compatible con mksh pero no con ksh93.Expresiones condicionales
[[ … ]]sintaxis de doble soporteLa sintaxis de doble parche de ksh es compatible con ATT ksh93 y mksh como en bash.
Operadores de archivos
Ksh93, mksh y bash admiten las mismas extensiones de POSIX, incluso
-acomo sinónimo obsoleto de-e,-k(adhesivo),-G(propiedad de egid),-O(propietario de euid),-ef(mismo archivo),-nt(más nuevo que),-ot(más antiguo que).-N FILE(modificado desde la última lectura) no es compatible con mksh.Mksh no tiene un operador de coincidencia de expresiones regulares
=~. Ksh93 tiene este operador, y realiza la misma coincidencia que en bash, pero no tiene el equivalente deBASH_REMATCHrecuperar grupos coincidentes después.Operadores de cadenas
Ksh93 y mksh admiten los mismos operadores de comparación de cadenas
<y>bash, así como el==sinónimo de=. Mksh no utiliza la configuración regional para determinar el orden lexicográfico, compara cadenas como cadenas de bytes.Otros operadores
-v VARpara probar si una variable está definida es específica de bash. En cualquier shell POSIX, puede usar[ -z "${VAR+1}" ].Builtins
aliasEl conjunto de caracteres permitidos en los nombres de alias no es el mismo en todos los shells. Creo que es lo mismo que para las funciones (ver arriba).
builtinKsh93 tiene una llamada incorporada
builtin, pero no ejecuta un nombre como un comando incorporado. Se usacommandpara omitir alias y funciones; Esto llamará a un incorporado si existe, de lo contrario, un comando externo (puede evitar esto conPATH= command error_out_if_this_is_not_a_builtin).callerEsto es específico de bash. Usted puede obtener un efecto similar con
.sh.fun,.sh.filey.sh.linenoen ksh93. En mksh hay al finLINENO.declare`local`typesetdeclarees un nombre específico de bash para ksh'stypeset. Usotypeset: también funciona en bash.Mksh define
localcomo un alias paratypeset. En ksh93, debe usartypeset(o definir un alias).Mksh no tiene matrices asociativas (están programadas para una versión aún no publicada).
No creo que haya un equivalente exacto de bash
typeset -t(función de rastreo) en ksh.cdKsh93 no tiene
-e.echoKsh93 y mksh procesan las opciones
-ey-ncomo en bash. Mksh también entiende-E, ksh93 no lo trata como una opción. La expansión de barra invertida está desactivada de forma predeterminada en ksh93, activada de forma predeterminada en mksh.enableKsh no proporciona una forma de deshabilitar los comandos incorporados. Para evitar una construcción, busque la ruta del comando externo e invoque explícitamente.
execKsh93 tiene
-apero no-l. Mksh no tiene ninguno.exportNi ksh93 ni mksh lo han hecho
export -n. Use en sutypeset +x foolugar, funciona en bash y ksh.Ksh no exporta funciones a través del entorno.
letletes lo mismo en bash y ksh.mapfile,readarrayEsta es una característica específica de bash. Puede usar
while readbucles o sustitución de comandos para leer un archivo y dividirlo en una matriz de líneas. CuidaIFSy pega. Aquí está el equivalente demapfile -t lines </path/to/file:printfprintfEs muy similar. Creo que ksh93 es compatible con todas las directivas de formato de bash. mksh no es compatible con%qo%(DATE_FORMAT)T; en algunas instalaciones,printfno es un mksh incorporado y llama al comando externo en su lugar.printf -v VARes específico de bash, ksh siempre imprime en salida estándar.readVarias opciones son específicas de bash, incluidas todas las de readline. Las opciones
-r,-d,-n,-N,-t,-uson idénticos en bash, ksh93 y mksh.readonlyPuede declarar una variable como de solo lectura en Ksh93 y mksh con la misma sintaxis. Si la variable es una matriz, primero debe asignarla y luego hacerla de solo lectura con
readonly VAR. Las funciones no se pueden hacer de solo lectura en ksh.set,shoptTodas las opciones
setyset -oson características de POSIX o ksh.shoptes específico de bash. Muchas opciones se refieren al uso interactivo de todos modos. Para conocer los efectos sobre el globbing y otras funciones habilitadas por algunas opciones, consulte la sección "Opciones" a continuación.sourceEsta variante de
.existe en ksh también. En bash y mksh,sourcebusca el directorio actual despuésPATH, pero en ksh93, es un equivalente exacto de..trapLa
DEBUGpseudo-señal no se implementa en mksh. En ksh93, existe con una forma diferente de informar información, consulte el manual para más detalles.typeEn ksh,
typees un alias parawhence -v. En mksh,type -pno imprime la ruta al ejecutable, sino un mensaje legible por humanos; necesitas usarwhence -p COMMANDen su lugar.Opciones
shopt -s dotglob- no ignore los archivos de puntos en globbingPara emular la
dotglobopción en ksh93, puede configurarFIGNORE='@(.|..)'. No creo que haya algo así en mksh.shopt -s extglob- patrones de globo extendido kshLa
extglobopción siempre está activada en ksh.shopt -s failglob- error si un patrón global no coincide con nadaNo creo que esto exista ni en mksh ni en ksh93. Lo hace en zsh (comportamiento por defecto a menos que
null_globocsh_null_globson set).shopt -s globstar-**/globo recursivoKsh93 tiene globbing recursivo con
**/, habilitado conset -G. Mksh no tiene globulación recursiva.shopt -s lastpipe- ejecuta el último comando de una tubería en el shell principalKsh93 siempre ejecuta el último comando de una tubería en el shell principal, que en bash requiere
lastpipeque se establezca la opción. Mksh siempre ejecuta el último comando de una tubería en una subshell.shopt -s nocaseglob,shopt -s nocasematch- patrones que no distinguen entre mayúsculas y minúsculasMksh no tiene coincidencia de patrones sin distinción entre mayúsculas y minúsculas. Ksh93 lo admite patrón por patrón: prefije el patrón con
~(i).shopt -s nullglob- expande patrones que no coinciden con ningún archivo a una lista vacíaMksh no tiene esto. Ksh93 lo admite patrón por patrón: prefije el patrón con
~(N).Variables
Obviamente, la mayoría de las
BASH_xxxvariables no existen en ksh.$BASHPIDse puede emular con el costoso pero portátilsh -c 'echo $PPID', y se ha agregado recientemente a mksh.BASH_LINEestá.sh.linenoen ksh93 yLINENOen mksh.BASH_SUBSHELLestá.sh.subshellen ksh93.Mksh y ksh93 obtienen el archivo proporcionado
ENVcuando se inician.EUIDyUIDno existen en ksh93. Mksh los llamaUSER_IDyKSH_UID; que no tieneGROUPS.FUNCNAMEyFUNCNESTno existen en ksh. Ksh93 tiene.sh.funy.sh.level. Las funciones declaradas confunction foo { …; }(¡sin paréntesis!) Tienen su propio nombre$0.GLOBIGNOREexiste en ksh93 pero con un nombre y una sintaxis diferentes: se llamaFIGNOREy es un patrón único, no una lista separada por dos puntos. Usa un@(…|…)patrón. KshFIGNOREsubsume bash, con una sintaxis completamente diferente.Ksh93 y mksh no tienen nada como
HOSTTYPE,MACHTYPEyOSTYPE. NiSHELLOPTSoTIMEFORMAT.Mksh sí
PIPESTATUS, pero ksh93 no.Mksh y ksh93 tienen
RANDOM.fuente
$BASHPIDpuede emular consh -c 'echo $PPID'? Lo intenté(sh -c 'echo $PPID')en Bash pero me da el mismo PID que$$.Esta pregunta es bastante amplia.
Tanto mksh como zsh son shells que admiten muchas extensiones específicas de bash de GNU , pero siempre hay algunas que no se entienden.
zsh admite más cosas, pero solo en su modo zsh nativo, que no es compatible con shells POSIX (como GNU bash, AT&T ksh93 , mksh). Además, mksh es mucho más delgado, más rápido y más portátil.
En general, si se trata de sus guiones que estamos hablando, seguir adelante, simplemente probarlos. (mksh todavía no admite matrices asociativas de estilo bash4. El comando "declare" es específico de bash, "typeset" es un equivalente. No estoy lo suficientemente familiarizado con zsh como para decir algo sobre eso directamente. ksh93 no tiene "local" pero también usa "typeset" para eso.) Pero si se trata, por ejemplo, de ejecutar un sistema Debian sin bash, olvídalo. La existencia de bash es parte de la "promesa" (API / ABI del sistema), y depende mucho de ella.
Descargo de responsabilidad: soy el desarrollador de mksh.
fuente
ZSH Comparación de proyectiles
No estoy familiarizado con mksh, así que no sé dónde buscar esa respuesta.
Si está buscando un reemplazo seguro para el shell, ninguno de estos shells difiere mucho de Bash en cuanto a la falla inherente que está discutiendo.
Un lenguaje como Perl maneja las entradas de manera más segura. Pero la mantenibilidad también es clave aquí. El reemplazo de shell Perl no está muy bien adoptado. Es responsabilidad del mantenedor de shell manejar las entradas de forma segura. Entonces, cuando escribes scripts, ¡ valida, valida, valida todo! ¡Use contratos de código para asegurar resultados correctos cada vez!
Perl Shell
Declaración de la FSF sobre el impacto de Shell
fuente
Una característica no habilitada por defecto en el
mkshhistorial de shell.En su
.mkshrcconjunto justo:export HISTFILE=~/.mksh-historyfuente