Расширение параметра, приводящее к пустой строке, обрабатывается по-разному.

10

Обновить

Кто - то в списке рассылки ошибка-Баш уже подтвердил это ошибка.


Если кому-то интересно, исправление доступно в последней ветке коммита для разработки .


Пока

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

печатает пустую строку,

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

печать bar.

Я не понимаю этого. ${1##*}разворачивается в пустую строку, поэтому "${1##*}"должен рассматриваться как ""есть, но кажется, что bash так не считает.

Похоже, что существует консенсус по этому поводу среди других популярных shреализаций:

$ 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 (с или без --posix) - единственный, не соответствующий этому:

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

И без обработки подстрок, поведение будет таким, как ожидалось:

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

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

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

$ 

Мне действительно интересно, есть ли объяснение этому, которое я не смог найти в руководстве. Это ошибка или неправильная интерпретация стандарта? Это поведение где-то задокументировано?


PS: я знаю, что быстрый обходной путь - это заключить в кавычки внутренний PE, но это не отвечает на мой вопрос и может привести к нежелательным результатам со строками, содержащими специальные символы.

Огуз Исмаил
источник
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)печатает пустую строку
Уильям Перселл
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)печатает "бар"
Уильям Перселл
@William протестирован на 4.4.20 и 5.0.11 и оба печатают «бар»
oguz ismail
Это кажется проблемой с расширением вообще. По моему 4.4.12(3)-release, echo "${BASH##*"${BASH##*}"}"-> /bin/bash. Пока echo "\${BASH##*"${BASH##*}"}"-> ${BASH##*}и eval echo "\${BASH##*"${BASH##*}"}"-> пусто.
Джефф Y

Ответы:

2

Это не ответ

Сначала я думал, что это из-за специальных глобальных правил, но в конце я думаю, что это ошибка в bash. Следующие четыре примера должны дать вам понять, почему я считаю, что это ошибка:

$ 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

Случай 1 и случай 3 отличаются в кавычках. Но для расширения параметров формы ${parameter##word}используются правила расширения пути word. Так *fooи *"foo"есть идентичное поведение в двойных кавычках в именах файлов может быть проигнорировано , если они не охватывают специальные символы шаблонов ( *, ?, ...). Это видно из следующего примера:

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

Так что, если это так, почему дела 2 и 4 должны вести себя по-разному?

kvantour
источник
почему дела 2 и 4 должны вести себя по-разному? Без причины оба ${1+}и ${1+""}расширяются до пустой строки, но они не обрабатываются так, как ${1##*}есть (см. Мое последнее редактирование). Таким образом, мы можем сделать вывод, что это ошибка, верно?
огузов исмаил
1
@oguzismail Точно! Если случай 1 и случай 3 ведут себя одинаково, то случай 2 и случай 4 также должны вести себя одинаково.
Квантур