Bash Parameter Substitution: command line vs. script

Pat*_*tin 4 bash shell-script bash-expansion

I am practicing with parameter substitution in bash.

I wrote the following dummy script:

#!/bin/bash

var1="/some/path/to/file/the_file.arbitrary.n.ext.0.random.ext"
var2="/some/path/to/file/the_file.arbitrary.n.ext.0.ext"

pattern='.[0-9]?(.random).ext'

echo "${pattern}"
echo "${var1/${pattern}/}"
echo "${var2/${pattern}/}"
Run Code Online (Sandbox Code Playgroud)

Basically, the pattern is meant to strip off the last part of the file name.


Executing the dummy script results in:

~$ ./dummy.sh 
.[0-9]?(.random).ext
/some/path/to/file/the_file.arbitrary.n.ext.0.random.ext
/some/path/to/file/the_file.arbitrary.n.ext.0.ext
Run Code Online (Sandbox Code Playgroud)

whereas evaling the script's contents or, equivalently, the direct input of that sequence of commands in the interactive shell, results in:

~$ eval "$(cat dummy.sh)"
.[0-9]?(.random).ext
/some/path/to/file/the_file.arbitrary.n.ext
/some/path/to/file/the_file.arbitrary.n.ext
Run Code Online (Sandbox Code Playgroud)

The pattern '.[0-9]*.ext' works, so the issue clearly is confined to the sub-string '?(.random)'. The issue could be with ?, since it is a reserved character in the context of parameter substitution. However, if that were the issue, I would expect the pattern to either fail or succeed the same in both cases.

Where's the probably obvious pitfall?

Nic*_*teo 10

The problem may be that the extglob shell option is set in the interactive shell, but not in the script shell.

$ shopt -u extglob
$ echo "${var1/${pattern}/}"
/some/path/to/file/the_file.arbitrary.n.ext.0.random.ext
$ shopt -s extglob
$ echo "${var1/${pattern}/}"
/some/path/to/file/the_file.arbitrary.n.ext
Run Code Online (Sandbox Code Playgroud)

So you can try putting shopt -s extglob right after the shebang line in the script.

From the Bash Reference Manual:

如果extglob使用shopt内置函数启用 shell 选项,则会识别多个扩展模式匹配运算符.... 可以使用以下一种或多种子模式形成复合模式:

?(PATTERN-LIST)
    匹配给定模式的零次或一次出现。