Розширення параметрів, що призводить до порожнього рядка, трактується по-різному


10

Оновлення

Хто - то в списку розсилки помилка-Баш вже підтвердив це помилка.


Якщо хтось зацікавлений, виправлення доступне в останньому зобов'язанні розробити галузь .


Поки

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

друкує порожній рядок,

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

відбитки bar.

Я цього не розумію. ${1##*}розширюється до порожнього рядка, тому "${1##*}"слід ставитися так само, як ""є, але здається, що Баш так не вважає.

З цього питання, мабуть, існує консенсус серед інших популярних 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##*}"}"-> пусті.
Jeff Y

Відповіді:


2

Це не відповідь

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

$ 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 повинні поводитися по-різному?


Чому Справа 2 та 4 повинні поводитися по-різному? Немає причин, ${1+}і ${1+""}розширюється до порожнього рядка, але вони не трактуються таким чином ${1##*}(див. Мою останню редакцію). Таким чином, ми можемо зробити висновок, що це помилка, правда?
Огуз Ісмаїл

1
@oguzismail Саме так! Якщо випадок 1 і випадок 3 поводяться однаково, то випадок 2 і випадок 4 також повинні поводитися однаково.
kvantour
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.