Reputation: 13
Why does the following code produce different output in ksh and bash
p="folderA/folderB/folderC"
echo ${p%%+([^/])}
echo ${p#${p%%+([^/])}}
ksh outputs:
folderA/folderB/
folderC
bash outputs:
folderA/folderB/folderC
I'm especially confused because I used the bash documentation to create this parameter expansion.
I want to extract the folder name after the last slash. I found another way which is working in ksh and bash:
echo ${p##*/}
but I would like to understand why the first approach is not working.
Upvotes: 0
Views: 185
Reputation: 50750
+(...)
is extended glob syntax, you need to enable extglob
feature for bash to understand it. And as stated in the other answer, normally a circumflex shouldn't be used for negating a character class. Bash tolerates this mistake, but anyways let's use the correct syntax for the sake of portability:
shopt -s extglob
p="folderA/folderB/folderC"
echo "${p%%+([!/])}"
echo "${p#${p%%+([!/])}}"
yields:
folderA/folderB/
folderC
Related link: Bash Reference Manual § Pattern Matching.
And btw, you don't really need extended globs for this.
p="folderA/folderB/folderC"
echo "${p%${p##*/}}"
echo "${p##*/}"
Above script works just as well on any POSIX-compliant shell.
Upvotes: 1
Reputation: 5317
Another, more standards-compliant, Korn shell actually outputs
folderA/folderB/folderC
followed by an empty line. This is because shell globs are not regular expressions, and the character class negotiation operator is a false friend.
In POSIX shell, [^/]
is actually unspecified but normally (["^"/]
is more clear) means “either ^
or /
” but you will want “anything that’s not /
” which, in POSIX shell globs, is [!/]
instead.
See the other answer for an explanation on how GNU bash needs shopt -s extglob
to support Korn shell-compatible extended globbing patterns in addition.
Upvotes: 1