Caractères de nom de fonction valides du shell

13

L'utilisation de caractères Unicode étendus est (sans aucun doute) utile pour de nombreux utilisateurs.

Les shells plus simples (ash (busybox), dash) et ksh échouent avec:

tést() { echo 34; }

tést

Mais , , et semblent le permettre.

Je suis conscient que les noms de fonction valides POSIX utilisent cette définition des noms . Cela signifie que cette expression régulière:

[a-zA-Z_][a-zA-Z0-9_]*

Cependant, dans le premier lien, il est également dit:

Une implémentation peut autoriser d'autres caractères dans un nom de fonction en tant qu'extension.

Les questions sont:

  • Est-ce accepté et documenté?
  • Où?
  • Pour quels obus (le cas échéant)?

Questions connexes:
Son possible utiliser des caractères spéciaux dans un nom de fonction shell?
Je ne suis pas intéressé à utiliser des méta-caractères (>) dans les noms de fonction.

Noms de fonction Upstart et bash contenant "-"
Je ne pense pas qu'un opérateur (soustraction "-") doive faire partie d'un nom.

Communauté
la source
vous pourriez trouver aliasun peu plus clément. et vous pouvez donc écrire la fonction avec un nom approprié et boutonné, puis définir simplement un alias nommé plus élégamment pour appeler la fonction. dans dashil y a aussi des choses que vous pouvez faire avec $PATHet %func.
mikeserv

Réponses:

16

Étant donné que la documentation POSIX l'autorise en tant qu'extension, rien n'empêche l'implémentation de ce comportement.

Une simple vérification (rodée zsh):

$ for shell in /bin/*sh 'busybox sh'; do
    printf '[%s]\n' $shell
    $=shell -c 'á() { :; }'
  done
[/bin/ash]
/bin/ash: 1: Syntax error: Bad function name
[/bin/bash]
[/bin/dash]
/bin/dash: 1: Syntax error: Bad function name
[/bin/ksh]
[/bin/lksh]
[/bin/mksh]
[/bin/pdksh]
[/bin/posh]
/bin/posh: á: invalid function name
[/bin/yash]
[/bin/zsh]
[busybox sh]
sh: syntax error: bad function name

montrer que bash, zsh, yash, ksh93(qui kshlié à mon système), pdkshet sa dérivation permettent des caractères multi-octets comme nom de la fonction.

yash est conçu pour prendre en charge les caractères multi-octets dès le début, il n'y a donc pas de surprise que cela fonctionne.

L'autre documentation que vous pouvez consulter est ksh93:

Un blanc est un onglet ou un espace. Un identifiant est une séquence de lettres, de chiffres ou de traits de soulignement commençant par une lettre ou un trait de soulignement. Les identificateurs sont utilisés comme composants des noms de variables. Un vname est une séquence d'un ou plusieurs identifiants séparés par un. et éventuellement précédé d'un .. Les Vnames sont utilisés comme noms de fonction et de variable. Un mot est une séquence de caractères du jeu de caractères défini par l'environnement local actuel , à l'exclusion des métacaractères non cités.

Donc, paramétrer sur Clocale:

$ export LC_ALL=C
$ á() { echo 1; }
ksh: á: invalid function name

faire échouer.

cuonglm
la source
poshne vaut pas d'être répertorié dans une telle liste. Cela dépend des bogues spécifiques à Linux libcet ne fonctionnera pas sur d'autres plates-formes.
schily
Je ne peux pas répéter vos affirmations sur l' ksh93utilisation d'un ksh93 auto-compilé à partir de sources originales. Bien qu'il ksh88semble accepter des lettres ASCII non 7 bits pour les noms de fonction, seul le ksh93binaire d'Ubuntu semble les accepter.
schily
@schily ksh que j'ai utilisé dans ce test est le binaire dans Debian (il peut donc en être de même avec celui sur Ubuntu)
cuonglm
9

Notez que les fonctions partagent le même espace de noms que d'autres commandes, y compris les commandes du système de fichiers, qui sur la plupart des systèmes n'ont aucune limitation sur les caractères ou même les octets qu'elles peuvent contenir dans leur chemin.

Ainsi, alors que la plupart des shells restreignent les caractères de leurs fonctions, il n'y a aucune vraie bonne raison pour laquelle ils feraient cela. Cela signifie que dans ces shells, il existe des commandes que vous ne pouvez pas remplacer par une fonction.

zshet rcautoriser quoi que ce soit pour leurs noms de fonction, y compris certains avec /et la chaîne vide. zshautorise même les octets NUL.

$ zsh
$ $'\0'() echo nul
$ ^@
nul
$ ""() uname
$ ''
Linux
$ /bin/ls() echo test
$ /bin/ls
test

Une commande simple dans le shell est une liste d'arguments, et le premier argument est utilisé pour dériver la commande à exécuter. Il est donc logique que ces arguments et noms de fonction partagent les mêmes valeurs possibles et que les arguments des fonctions zshintégrées et des fonctions puissent être n'importe quelle séquence d'octets.

Il n'y a pas de problème de sécurité ici car les fonctions que vous (l'auteur du script) définissez sont celles que vous invoquez.

Là où il peut y avoir des problèmes de sécurité, c'est lorsque l'analyse est affectée par l'environnement, par exemple avec des shells où les noms valides pour les fonctions sont affectés par les paramètres régionaux.

Stéphane Chazelas
la source
On peut jouer à des jeux en bash aussi, à commencer par function /bin/sh { echo "$0: $FUNCNAME: Permission denied"; return 126; }, et potentiellement choses utiles aussi avec des fonctions nommées --, //, @ou %etc.
mr.spuratic
mais les shells n'ont-ils pas tendance à contourner une recherche de table de hachage quand /on le trouve dans un nom? et une fonction n'est pas seulement un nom exécutable - son code. Je pense qu'une simple implémentation pourrait rencontrer beaucoup de problèmes d'analyse si ses noms de fonction stockés comprenaient des métacaractères.
mikeserv
Oui, je suis conscient de l'incapacité de bash à contenir des valeurs nulles dans vars, qui pourraient être raisonnablement étendues aux noms de fonction. Je n'ai pas d'exemple spécifique, mais je pense que ce jeu consistant à autoriser presque n'importe quoi pour les noms est plus une faille de sécurité potentielle qu'un "moyen facile de travailler". J'espère que je me trompe.