Расширение параметров оболочки работает в ksh, но не в bash

Почему следующий код выдает разные результаты в ksh и bash

p="folderA/folderB/folderC"
echo ${p%%+([^/])}
echo ${p#${p%%+([^/])}}

кш выходы:

folderA/folderB/
folderC

Баш выходы:

folderA/folderB/folderC

Я особенно запутался, потому что использовал документацию bash для создания расширения этого параметра.

Я хочу извлечь имя папки после последней косой черты. Я нашел другой способ, который работает в ksh и bash:

echo ${p##*/}

но я хотел бы понять, почему первый подход не работает.


person pr0nk    schedule 08.10.2019    source источник
comment
Какая у вас версия Баша? Я получаю правильный вывод на моем bash 5.0.11 the folder name after the last slash - используйте basename для большей переносимости. Используйте dirname для части перед последней косой чертой.   -  person KamilCuk    schedule 08.10.2019
comment
Я получаю одну строку с bash (4.4.20), zsh и dash. Две строчки с кш93.   -  person Shawn    schedule 08.10.2019


Ответы (2)


+(...) — это расширенный синтаксис glob, вам нужно включить функцию extglob, чтобы bash понимал ее. И, как указано в другом ответе, обычно циркумфлекс не следует использовать для отрицания класса символов. Bash терпит эту ошибку, но в любом случае давайте использовать правильный синтаксис ради переносимости:

shopt -s extglob
p="folderA/folderB/folderC"
echo "${p%%+([!/])}"
echo "${p#${p%%+([!/])}}"

дает:

folderA/folderB/
folderC

Ссылка по теме: Справочное руководство Bash § Сопоставление шаблонов< /а>.


И кстати, для этого вам действительно не нужны расширенные глобусы.

p="folderA/folderB/folderC"
echo "${p%${p##*/}}"
echo "${p##*/}"

Приведенный выше скрипт работает так же хорошо в любой POSIX-совместимой оболочке.

person oguz ismail    schedule 08.10.2019

Другая, более совместимая со стандартами оболочка Korn фактически выводит

folderA/folderB/folderC

затем пустая строка. Это связано с тем, что шаблоны оболочки не являются регулярными выражениями, а оператор согласования класса символов является ложным другом.

В оболочке POSIX [^/] на самом деле не указано, но обычно (["^"/] более понятно) означает «либо ^, либо /», но вам понадобится «все, что не /», что в глобах оболочки POSIX вместо этого равно [!/].

См. другой ответ для объяснения того, как GNU bash требуется shopt -s extglob для поддержки расширенных шаблонов подстановки, совместимых с оболочкой Korn.

person mirabilos    schedule 09.10.2019