¿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/sh
con 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
sh
shell 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 unacase
declaración, pero no;;&
para 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 usofunction
de 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 -l
ytypeset -u
tanto 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 deVAR
isOTHERVAR
(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 extglob
activarse 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/PORT
La expansión de comodines en una redirección en los scripts (como por
var="*.txt"; echo hello >$a
escritoa.txt
si 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
>&
para 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
-a
como 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_REMATCH
recuperar 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 VAR
para probar si una variable está definida es específica de bash. En cualquier shell POSIX, puede usar[ -z "${VAR+1}" ]
.Builtins
alias
El 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).
builtin
Ksh93 tiene una llamada incorporada
builtin
, pero no ejecuta un nombre como un comando incorporado. Se usacommand
para 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
).caller
Esto es específico de bash. Usted puede obtener un efecto similar con
.sh.fun
,.sh.file
y.sh.lineno
en ksh93. En mksh hay al finLINENO
.declare
`local
`typeset
declare
es un nombre específico de bash para ksh'stypeset
. Usotypeset
: también funciona en bash.Mksh define
local
como 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.cd
Ksh93 no tiene
-e
.echo
Ksh93 y mksh procesan las opciones
-e
y-n
como 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.enable
Ksh no proporciona una forma de deshabilitar los comandos incorporados. Para evitar una construcción, busque la ruta del comando externo e invoque explícitamente.
exec
Ksh93 tiene
-a
pero no-l
. Mksh no tiene ninguno.export
Ni ksh93 ni mksh lo han hecho
export -n
. Use en sutypeset +x foo
lugar, funciona en bash y ksh.Ksh no exporta funciones a través del entorno.
let
let
es lo mismo en bash y ksh.mapfile
,readarray
Esta es una característica específica de bash. Puede usar
while read
bucles o sustitución de comandos para leer un archivo y dividirlo en una matriz de líneas. CuidaIFS
y pega. Aquí está el equivalente demapfile -t lines </path/to/file
:printf
printf
Es muy similar. Creo que ksh93 es compatible con todas las directivas de formato de bash. mksh no es compatible con%q
o%(DATE_FORMAT)T
; en algunas instalaciones,printf
no es un mksh incorporado y llama al comando externo en su lugar.printf -v VAR
es específico de bash, ksh siempre imprime en salida estándar.read
Varias opciones son específicas de bash, incluidas todas las de readline. Las opciones
-r
,-d
,-n
,-N
,-t
,-u
son idénticos en bash, ksh93 y mksh.readonly
Puede 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
,shopt
Todas las opciones
set
yset -o
son características de POSIX o ksh.shopt
es 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.source
Esta variante de
.
existe en ksh también. En bash y mksh,source
busca el directorio actual despuésPATH
, pero en ksh93, es un equivalente exacto de.
.trap
La
DEBUG
pseudo-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.type
En ksh,
type
es un alias parawhence -v
. En mksh,type -p
no imprime la ruta al ejecutable, sino un mensaje legible por humanos; necesitas usarwhence -p COMMAND
en su lugar.Opciones
shopt -s dotglob
- no ignore los archivos de puntos en globbingPara emular la
dotglob
opción en ksh93, puede configurarFIGNORE='@(.|..)'
. No creo que haya algo así en mksh.shopt -s extglob
- patrones de globo extendido kshLa
extglob
opció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_glob
ocsh_null_glob
son 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
lastpipe
que 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_xxx
variables no existen en ksh.$BASHPID
se puede emular con el costoso pero portátilsh -c 'echo $PPID'
, y se ha agregado recientemente a mksh.BASH_LINE
está.sh.lineno
en ksh93 yLINENO
en mksh.BASH_SUBSHELL
está.sh.subshell
en ksh93.Mksh y ksh93 obtienen el archivo proporcionado
ENV
cuando se inician.EUID
yUID
no existen en ksh93. Mksh los llamaUSER_ID
yKSH_UID
; que no tieneGROUPS
.FUNCNAME
yFUNCNEST
no existen en ksh. Ksh93 tiene.sh.fun
y.sh.level
. Las funciones declaradas confunction foo { …; }
(¡sin paréntesis!) Tienen su propio nombre$0
.GLOBIGNORE
existe en ksh93 pero con un nombre y una sintaxis diferentes: se llamaFIGNORE
y es un patrón único, no una lista separada por dos puntos. Usa un@(…|…)
patrón. KshFIGNORE
subsume bash, con una sintaxis completamente diferente.Ksh93 y mksh no tienen nada como
HOSTTYPE
,MACHTYPE
yOSTYPE
. NiSHELLOPTS
oTIMEFORMAT
.Mksh sí
PIPESTATUS
, pero ksh93 no.Mksh y ksh93 tienen
RANDOM
.fuente
$BASHPID
puede 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
mksh
historial de shell.En su
.mkshrc
conjunto justo:export HISTFILE=~/.mksh-history
fuente