L'expansion des paramètres entraînant une chaîne vide est traitée différemment


10

Mise à jour

Un membre de la liste de diffusion bug-bash a confirmé qu'il s'agit d'un bogue.


Si quelqu'un est intéressé, un correctif est disponible dans la dernière branche commit to devel .


Tandis que

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

imprime une ligne vide,

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

impressions bar .

Je ne comprends pas ça. ${1##*}se développe en une chaîne vide, "${1##*}"doit donc être traité comme"" tel quel, mais il semble que bash ne le pense pas.

Il semble y avoir un consensus à ce sujet parmi les autres shimplémentations populaires :

$ 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 non conforme à cela:

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

Et sans trucs de traitement de sous-chaîne, le comportement est comme prévu:

$ 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 pu trouver dans le manuel. Est-ce un bug ou une mauvaise interprétation de la norme? Ce comportement est-il documenté quelque part?


PS: Je sais qu'une solution rapide consiste à ne pas 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.


GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)imprime une chaîne vide
William Pursell

GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)imprime "bar"
William Pursell

@William testé sur 4.4.20 et 5.0.11 et les deux "barre" d'impression
oguz ismail

Cela semble être un problème avec l'expansion en général. Dans mon 4.4.12(3)-release, echo "${BASH##*"${BASH##*}"}"-> /bin/bash. Alors que echo "\${BASH##*"${BASH##*}"}"-> ${BASH##*}et eval echo "\${BASH##*"${BASH##*}"}"-> vide.
Jeff Y

Réponses:


2

Ce n'est pas une réponse

Je pensais d'abord que cela était dû à des règles globales spéciales, mais à la fin je pense que c'est un bug dans bash. Les quatre exemples suivants devraient vous donner une idée pourquoi je pense que c'est un bug:

$ 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 du formulaire ${parameter##word}utilise des règles d'expansion des noms de chemin à traiter word. Donc , *fooet *"foo"ont un comportement identique des guillemets doubles dans l' expansion du chemin peut être ignorée à moins qu'ils embrassent des caractères spéciaux motif ( *, ?, ...). Cela se 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 tel est le cas, pourquoi le cas 2 et le cas 4 devraient-ils se comporter différemment?


pourquoi le cas 2 et le cas 4 devraient-ils se comporter différemment? Aucune raison, à la fois ${1+}et se ${1+""}développe en chaîne vide, mais ils ne sont pas traités de la même façon ${1##*}(voir ma dernière modification). On peut donc en déduire que c'est un bug, non?
oguz ismail

1
@oguzismail Exactement! Si le cas 1 et le cas 3 se comportent de manière identique, le cas 2 et le cas 4 doivent également se comporter de manière identique.
kvantour
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.