Esto funciona perfectamente en OSX
#!/bin/bash
chars=( {a..z} )
n=3
for ((i=0; i<n; i++))
do
echo "${chars[i]}"
done
Pero cuando lo ejecuto en Ubuntu, aparece el siguiente error.
ForLoopAlphabetTest.sh: 2: ForLoopAlphabetTest.sh: Syntax error: "(" unexpected
Parece que no puedo resolver el problema. ¿Alguna sugerencia?

Respuestas:
Presumiblemente, está ejecutando el script como:
En Ubuntu,
shestá vinculado adash; comodashno tiene concepto de matrices, está obteniendo el error de sintaxis para(.El script funciona perfectamente
bash, por lo que estaría bien si lo estuviera ejecutando comobashargumento:Ahora, tiene el
bashshebang en el script, por lo que puede hacer que el script sea ejecutable (chmod u+x ForLoopAlphabetTest.sh) y ejecutarlo como:o desde el directorio del script:
También tenga en cuenta que su script contiene expansión de llaves
{a..z}yforconstrucción de estilo C :for (( ... ))que tampoco son compatibles condash; así que si su objetivo es la portabilidad, debe mirarshsolo las sintaxis POSIX .fuente
/bin/shen cualquier sistema operativo tipo Unix, entonces no podrá usar matrices. Bash (y algunos otros shells) los han agregado porque son muy convenientes y no siempre se pueden reemplazar fácilmente con un código más portátil. Sin embargo, para su script en particular, puede hacerlo sin problemas y sin usar ninguna característica específica de bash. ¿Estás interesado en cómo hacer eso?shSu 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 desh. Su línea hashbang en la parte superior (#!/bin/bash) especificabashpero solo es efectiva si ejecuta el script, como explicó heemayl . Si pasa el nombre del script ash,shno llamará automáticamentebash, 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:
( {a..z} ), que asignachars, crea una matriz y${chars[i]}, que aparece en su bucle, se indexa en ella.{a..z}se expande aa 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.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), elforbucle de estilo C es un Bash-ism y no es ampliamente portátil para otras conchasBash 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 C
forbucle 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:
seqcomando genera secuencias numéricas.$()realiza la sustitución de comandos , por lo que$(seq 97 122)se reemplaza con la salida deseq 97 122. Estos son los códigos de caracteres paraatravész.printfcomando puede convertir los códigos de caracteres en letras (p. Ej.,printf '\141'Impresionesa, seguidas de una nueva línea ), pero los códigos deben estar en octal , mientras queseqsolo se muestran en decimal . Así que he usadoprintfdos veces: el internoprintf %o $iconvierte los números decimales (proporcionados porseq) a octal, y se sustituye en elprintfcomando 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\antesnno necesita escapar porque, a diferencia\$,\nno tiene un significado especial para el shell en una cadena entre comillas dobles.') 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 usarjoten su lugar, que no está instalado por defecto en la mayoría de los sistemas GNU / Linux). Puedes usar un bucle conexpro una sustitución aritmética para aumentar aún más la portabilidad, si necesita: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 requiereseq: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: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 hacerstop=$((i + n - 1))y usar[ $i -le $stop ]).fuente