10 votes

L'expansion de paramètre résultant en une chaîne vide est traitée différemment

Mise à jour

Quelqu'un dans liste de diffusion bug-bash tiene confirmé c'est un bug.


Si quelqu'un est intéressé, un correctif est disponible en le dernier commit de la branche devel .


Alors que

bash -c 'echo "${1##*""}"' _ bar

imprime une ligne vide,

bash -c 'echo "${1##*"${1##*}"}"' _ bar

imprime bar .

Je ne comprends pas. ${1##*} se développe en une chaîne vide, donc "${1##*}" doivent être traitées comme "" est, mais il semble que Bash ne le pense pas.

Il semble qu'il y ait un consensus à ce sujet parmi d'autres personnes populaires. sh mises en œuvre :

$ sh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ash -c 'echo "${1##*"${1##*}"}"' _ bar

$ dash -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh93 -c 'echo "${1##*"${1##*}"}"' _ bar

$ mksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ posh -c 'echo "${1##*"${1##*}"}"' _ bar

$ yash -c 'echo "${1##*"${1##*}"}"' _ bar

$ zsh -c 'echo "${1##*"${1##*}"}"' _ bar

$

bash (avec ou sans --posix ) est le seul à ne pas s'y conformer :

$ bash -c 'echo "${1##*"${1##*}"}"' _ bar
bar

Et sans traitement des sous-chaînes, le comportement est conforme aux attentes :

$ bash -c 'echo "${1##*"${1+}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar ''

$ 

Je me demande vraiment s'il y a une explication à cela, que je n'ai pas trouvée dans le manuel. S'agit-il d'un bogue ou d'une mauvaise interprétation de la norme ? Ce comportement est-il documenté quelque part ?


PS : Je sais qu'une solution de contournement rapide consiste à dé-citer le PE interne, mais cela ne répond pas à ma question, et peut conduire à des résultats indésirables avec des chaînes contenant des caractères spéciaux.

2voto

kvantour Points 11497

Ce n'est pas une réponse

J'ai d'abord pensé que cela était dû à des règles globales spéciales, mais finalement je pense que c'est un bogue dans bash. Les quatre exemples suivants devraient vous donner une idée de la raison pour laquelle je pense que c'est un bogue :

$ bash -c 'echo "${1##*${1%%bar}}"' _ foobar        # case 1
bar
$ bash -c 'echo "${1##*${1%%foobar}}"' _ foobar     # case 2

$ bash -c 'echo "${1##*"${1%%bar}"}"' _ foobar      # case 3
bar
$ bash -c 'echo "${1##*"${1%%foobar}"}"' _ foobar   # case 4
foobar

Le cas 1 et le cas 3 diffèrent dans les citations. Mais l'expansion des paramètres de la forme ${parameter##word} utiliser les règles d'expansion de nom de chemin pour traiter word . Donc *foo y *"foo" ont un comportement identique à celui des guillemets dans l'expansion d'un nom de chemin et peuvent être ignorés à moins qu'ils n'englobent des caractères de motif spéciaux ( * , ? ,...). On le voit dans l'exemple suivant :

$ bash -c 'echo "${1##*${2%%b*r}}"' _ 'foobar' 'f*ob*r'
bar
$ bash -c 'echo "${1##*"${2%%b*r}"}"' _ 'foobar' 'f*ob*r'
foobar

Si c'est le cas, pourquoi le cas 2 et le cas 4 devraient-ils se comporter différemment ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X