Die Parametererweiterung, die zu einer leeren Zeichenfolge führt, wird unterschiedlich behandelt

10

Aktualisieren

Jemand in der Bug-Bash-Mailingliste hat bestätigt, dass dies ein Fehler ist.


Wenn jemand interessiert ist, ist ein Fix im neuesten Commit zur Entwicklung des Zweigs verfügbar .


Während

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

druckt eine leere Zeile,

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

druckt bar.

Ich verstehe das nicht ${1##*}Erweitert sich zu einer leeren Zeichenfolge, "${1##*}"sollte also so behandelt werden, wie es ""ist, aber Bash scheint das nicht zu glauben.

Diesbezüglich scheint es unter anderen populären shImplementierungen einen Konsens zu geben :

$ 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 (mit oder ohne --posix) ist der einzige, der dem nicht entspricht:

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

Und ohne Dinge, die Teilzeichenfolgen verarbeiten, ist das Verhalten wie erwartet:

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

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

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

$ 

Ich frage mich wirklich, ob es dafür eine Erklärung gibt, die ich im Handbuch nicht finden konnte. Ist das ein Fehler oder eine Fehlinterpretation des Standards? Ist dieses Verhalten irgendwo dokumentiert?


PS: Ich weiß, dass eine schnelle Problemumgehung darin besteht, das innere PE aufzuheben, aber das beantwortet meine Frage nicht und kann zu unerwünschten Ergebnissen mit Zeichenfolgen führen, die Sonderzeichen enthalten.

oguz ismail
quelle
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)druckt eine leere Zeichenfolge
William Pursell
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)druckt "bar"
William Pursell
@ William getestet am 4.4.20 und 5.0.11 und beide drucken "bar"
oguz ismail
Dies scheint generell ein Problem bei der Expansion zu sein. In meinem 4.4.12(3)-release, echo "${BASH##*"${BASH##*}"}"-> /bin/bash. Während echo "\${BASH##*"${BASH##*}"}"-> ${BASH##*}und eval echo "\${BASH##*"${BASH##*}"}"-> leer.
Jeff Y

Antworten:

2

Dies ist keine Antwort

Zuerst dachte ich, dass dies auf spezielle Glob-Regeln zurückzuführen ist, aber am Ende denke ich, dass dies ein Fehler in der Bash ist. Die folgenden vier Beispiele sollen Ihnen ein Gefühl geben, warum ich glaube, dass dies ein Fehler ist:

$ 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

Fall 1 und Fall 3 unterscheiden sich in den Anführungszeichen. Die Parametererweiterung des Formulars ${parameter##word}verwendet jedoch Verarbeitungsregeln für Pfadnamen zur Verarbeitung word. So *foound *"foo"haben identisches Verhalten wie doppelte Anführungszeichen in Pfadnamen Expansion ignoriert werden kann , wenn sie spezielle Muster Zeichen umfassen ( *, ?, ...). Dies ist im folgenden Beispiel zu sehen:

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

Wenn dies der Fall ist, warum sollten sich Fall 2 und Fall 4 unterschiedlich verhalten?

kvantour
quelle
Warum sollten sich Fall 2 und Fall 4 unterschiedlich verhalten? Kein Grund, beides ${1+}und wird ${1+""}zu einer leeren Zeichenfolge erweitert, aber sie werden nicht so behandelt, wie es ${1##*}ist (siehe meine letzte Bearbeitung). Wir können also ableiten, dass dies ein Fehler ist, oder?
Oguz Ismail
1
@oguzismail Genau! Wenn sich Fall 1 und Fall 3 identisch verhalten, sollten sich auch Fall 2 und Fall 4 identisch verhalten.
kvantour