Votre script utilise trois fonctionnalités du shell Bash qui ne sont pas fournies par tous les shells de style Bourne. Comme le dit heemayl , vous pouvez simplement exécuter ce script avec bash
au lieu de sh
. Votre ligne de hachage en haut ( #!/bin/bash
) spécifie bash
mais n'est efficace que si vous exécutez le script, comme l' explique heemayl . Si vous passez le nom du script à sh
, sh
n'appellera pas automatiquement bash
, mais exécutera simplement le script. En effet, une fois votre script en cours d'exécution, la ligne de hachage n'a aucun effet .
Votre autre alternative, si vous avez besoin d'écrire des scripts entièrement portables qui ne dépendent pas des fonctionnalités de Bash, est de changer votre script pour qu'il fonctionne sans eux. Les fonctionnalités Bash que vous utilisez sont:
- Un tableau . Cela est arrivé en premier, c'est donc ce qui a produit l'erreur lorsque vous avez essayé d'exécuter votre script avec le shell Dash . L'expression entre parenthèses
( {a..z} )
, à laquelle vous attribuez chars
, crée un tableau et ${chars[i]}
, qui apparaît dans votre boucle, y indexe.
- Expansion du corset. Dans Bash, et aussi dans de nombreux autres obus,
{a..z}
est étendu à 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
. Cependant, ce n'est pas une fonctionnalité universelle (ou standardisée) des shells de style Bourne, et Dash ne la prend pas en charge.
- Le style C autre
for
syntaxe -loop . Bien que basée sur une expansion arithmétique , qui n'est pas elle-même spécifique à Bash (bien que certains shells très anciens et non conformes à POSIX ne l'aient pas non plus), la for
boucle de style C est un Bash-ism et n'est pas largement portable pour d'autres coquilles.
Bash est largement disponible, en particulier sur les systèmes GNU / Linux comme Ubuntu, et (comme vous l'avez vu) est également disponible sur macOS et de nombreux autres systèmes. Considérant combien vous utilisez des fonctionnalités spécifiques à Bash, vous pouvez simplement les utiliser, et assurez-vous simplement que vous utilisez Bash (ou un autre shell qui prend en charge les fonctionnalités que vous utilisez) lorsque vous exécutez vos scripts.
Cependant, vous pouvez les remplacer par des constructions portables si vous le souhaitez. Le tableau et la for
boucle de style C sont faciles à remplacer; générer la gamme de lettres sans expansion d'accolade (et sans les coder en dur dans votre script) est la partie qui est un peu délicate.
Tout d'abord, voici un script qui imprime toutes les lettres latines minuscules:
#!/bin/sh
for i in $(seq 97 122); do
printf "\\$(printf %o $i)\n"
done
- La
seq
commande génère des séquences numériques. $(
)
effectue la substitution de commande , $(seq 97 122)
est donc remplacé par la sortie de seq 97 122
. Ce sont les codes de caractères pour a
through z
.
- La puissante
printf
commande peut transformer les codes de caractères en lettres (par exemple, des printf '\141'
impressions a
, suivies d'une nouvelle ligne ), mais les codes doivent être en octal , tandis que les seq
sorties ne sont qu'en décimal . J'ai donc utilisé printf
deux fois: l'intérieur printf %o $i
convertit les nombres décimaux (fournis par seq
) en octal, et est substitué dans la printf
commande externe . (Bien qu'il soit également possible d'utiliser l' hexadécimal , ce n'est pas plus simple et semble moins portable .)
printf
interprète \
suivi d'un nombre octal comme caractère avec ce code et \n
comme nouvelle ligne. Mais le shell utilise également \
un caractère d'échappement. Un \
devant $
empêchera $
de provoquer une expansion (dans ce cas, la substitution de commande ), mais je ne veux pas empêcher cela, donc je l'ai échappé avec un autre \
; c'est la raison \\
. Le deuxième \
avant n
n'a pas besoin d'être échappé car, contrairement à \$
, \n
n'a pas de signification particulière pour le shell dans une chaîne entre guillemets.
- Pour plus d'informations sur l'utilisation des guillemets doubles et de la barre oblique inverse dans la programmation shell, consultez la section sur les citations dans la norme internationale . Voir aussi 3.1.2 Citation dans le Manuel de référence de Bash , en particulier 3.1.2.1 Caractère d'échappement et 3.1.2.3 Double guillemets . (Voici la section entière , dans son contexte.) Notez que les guillemets simples (
'
) sont également une partie importante de la syntaxe des citations du shell, je ne les ai simplement pas utilisés dans ce script.
Il est portable sur la plupart des systèmes de type Unix et ne dépend pas du shell de style Bourne que vous utilisez. Cependant, quelques systèmes de type Unix ne sont pas seq
installés par défaut (ils ont tendance à utiliser à la jot
place, qui n'est pas installé par défaut la plupart des systèmes GNU / Linux). Vous pouvez utiliser une boucle avec expr
ou une substitution arithmétique pour augmenter encore la portabilité, si vous devez:
#!/bin/sh
i=97
while [ $i -le 122 ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Cela utilise une while
boucle avec la [
commande pour continuer à boucler uniquement lorsqu'il $i
est à portée.
Plutôt que d'imprimer l'alphabet entier, votre script définit une variable n
et imprime les premières $n
lettres minuscules. Voici une version de votre script qui ne repose sur aucune fonctionnalité spécifique à Bash et fonctionne sur Dash, mais nécessite seq
:
#!/bin/sh
n=3 start=97
for i in $(seq $start $((start + n - 1))); do
printf "\\$(printf %o $i)\n"
done
Ajuster la valeur des n
changements combien de lettres sont imprimées, comme dans votre script.
Voici une version qui ne nécessite pas seq
:
#!/bin/sh
n=3 i=97 stop=$((i + n))
while [ $i -lt $stop ]; do
printf "\\$(printf %o $i)\n"
i=$((i + 1))
done
Là, il $stop
y en a un de plus que le code de caractère de la dernière lettre qui doit être imprimé, donc j'utilise -lt
(moins que) plutôt que -le
(inférieur ou égal) avec la [
commande. (Il aurait également fonctionné pour fabriquer stop=$((i + n - 1))
et utiliser [ $i -le $stop ]
).