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 bashlugar de sh. Su línea hashbang en la parte superior ( #!/bin/bash) especifica bashpero solo es efectiva si ejecuta el script, como explicó heemayl . Si pasa el nombre del script a sh, shno 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
forsintaxis -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 forbucle 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
seqcomando 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
printfcomando 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 seqsolo se muestran en decimal . Así que he usado printfdos veces: el interno printf %o $iconvierte los números decimales (proporcionados por seq) a octal, y se sustituye en el printfcomando externo . (Aunque también es posible usar hexadecimal , no es más simple y parece ser menos portátil ).
printfinterpreta \seguido de un número octal como el carácter con ese código y \ncomo 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 \$, \nno 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 seqinstalado por defecto (tienden a usar joten 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 whilebucle con el [comando para continuar haciendo bucles solo cuando $iestá dentro del rango.
En lugar de imprimir todo el alfabeto, su script define una variable ne imprime las primeras $nletras 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 ncambios 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 $stopuno 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 ]).