Su script utiliza tres características del shell Bash que no son provistas por todos los shells de estilo Bourne. Como dice heemayl , simplemente puede ejecutar ese script con en bash
lugar de sh
. Su línea hashbang en la parte superior ( #!/bin/bash
) especifica bash
pero solo es efectiva si ejecuta el script, como explicó heemayl . Si pasa el nombre del script a sh
, sh
no llamará automáticamente bash
, sino que simplemente ejecutará el script. Esto se debe a que una vez que su script se está ejecutando, la línea hashbang no tiene ningún efecto .
Su otra alternativa, si necesita escribir scripts totalmente portátiles que no dependan de las funciones de Bash, es cambiar su script para que funcione sin ellos. Las características de Bash que usa son:
- Un array . Esto vino primero, así que esto es lo que produjo el error cuando trataste de ejecutar tu script con el shell Dash . La expresión entre paréntesis
( {a..z} )
, que asigna chars
, crea una matriz y ${chars[i]}
, que aparece en su bucle, se indexa en ella.
- Expansión de la abrazadera. En Bash, y también en muchos otros shells,
{a..z}
se expande a a b c d e f g h i j k l m n o p q r s t u v w x y z
. Sin embargo, esta no es una característica universal (o estandarizada) de los shells de estilo Bourne, y Dash no lo admite.
- El estilo C alternativo
for
sintaxis -loop . Aunque se basa en la expansión aritmética , que no es específica de Bash (aunque algunos shells muy antiguos y no compatibles con POSIX tampoco lo tienen), el for
bucle de estilo C es un Bash-ism y no es ampliamente portátil para otras conchas
Bash está ampliamente disponible, especialmente en sistemas GNU / Linux como Ubuntu, y (como ha visto) también está disponible en macOS y muchos otros sistemas. Teniendo en cuenta cuánto está usando las funciones específicas de Bash, es posible que solo desee usarlas, y simplemente asegúrese de estar usando Bash (o algún otro shell que admita las funciones que está usando) cuando ejecuta sus scripts.
Sin embargo, puede reemplazarlos con construcciones portátiles si lo desea. La matriz y el estilo Cfor
bucle de son fáciles de reemplazar; Generar el rango de letras sin expansión de llaves (y sin codificarlas en su script) es la parte que es un poco complicada.
Primero, aquí hay un script que imprime todas las letras latinas en minúsculas:
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
- El
seq
comando genera secuencias numéricas. $(
)
realiza la sustitución de comandos , por lo que $(seq 97 122)
se reemplaza con la salida de seq 97 122
. Estos son los códigos de caracteres paraa
través z
.
- El poderoso
printf
comando puede convertir los códigos de caracteres en letras (p. Ej., printf '\141'
Impresiones a
, seguidas de una nueva línea ), pero los códigos deben estar en octal , mientras que seq
solo se muestran en decimal . Así que he usado printf
dos veces: el interno printf %o $i
convierte los números decimales (proporcionados por seq
) a octal, y se sustituye en el printf
comando externo . (Aunque también es posible usar hexadecimal , no es más simple y parece ser menos portátil ).
printf
interpreta \
seguido de un número octal como el carácter con ese código y \n
como una nueva línea. Pero el caparazón también se usa \
como un personaje de escape. Un \
frente $
impedirá $
a partir causando una expansión que se produzca (en este caso, la sustitución de comandos ), pero no quiero para evitar que, por lo que he escapado con otro \
; Ese es el motivo \\
. El segundo \
antesn
no necesita escapar porque, a diferencia \$
, \n
no tiene un significado especial para el shell en una cadena entre comillas dobles.
- Para obtener más información sobre cómo se utilizan las comillas dobles y la barra diagonal inversa en la programación de shell, consulte la sección sobre comillas en el estándar internacional . Consulte también 3.1.2 Citas en el Manual de referencia de Bash , especialmente 3.1.2.1 Carácter de escape y 3.1.2.3 Comillas dobles . (Aquí está la sección completa , en contexto.) Tenga en cuenta que las comillas simples (
'
) también son una parte importante de la sintaxis de comillas de shell, simplemente no las he usado en ese script.
Esto es portátil para la mayoría de los sistemas tipo Unix y no depende de qué shell Bourne use. Sin embargo, algunos sistemas similares a Unix no se han seq
instalado por defecto (tienden a usar jot
en su lugar, que no está instalado por defecto en la mayoría de los sistemas GNU / Linux). Puedes usar un bucle conexpr
o una sustitución aritmética para aumentar aún más la portabilidad, si necesita:
#!/bin/sh
i=97
while [ $i -le 122 ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Eso usa un while
bucle con el [
comando para continuar haciendo bucles solo cuando $i
está dentro del rango.
En lugar de imprimir todo el alfabeto, su script define una variable n
e imprime las primeras $n
letras minúsculas. Aquí hay una versión de su script que no se basa en características específicas de Bash y funciona en Dash, pero requiere seq
:
#!/bin/sh
n=3 start=97
for i in $(seq $start $((start + n - 1))); do
printf "\\$(printf %o $i)\n"
done
Ajustar el valor de los n
cambios cuántas letras se imprimen, como en su secuencia de comandos.
Aquí hay una versión que no requiere seq
:
#!/bin/sh
n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Hay $stop
uno más alto que el código de caracteres de la última letra que debe imprimirse, por lo que uso -lt
(menor que) en lugar de -le
(menor o igual) con el [
comando. (También habría funcionado para hacer stop=$((i + n - 1))
y usar [ $i -le $stop ]
).