Shell 参数扩展在 ksh 中有效但在 bash 中无效
Shell parameter expansion working in ksh but not in bash
为什么以下代码在 ksh 和 bash
中产生不同的输出
p="folderA/folderB/folderC"
echo ${p%%+([^/])}
echo ${p#${p%%+([^/])}}
ksh 输出:
folderA/folderB/
folderC
bash 输出:
folderA/folderB/folderC
我特别困惑,因为我使用 bash documentation 创建了这个参数扩展。
我想提取最后一个斜杠后的文件夹名称。我找到了另一种在 ksh 和 bash:
中工作的方法
echo ${p##*/}
但我想了解为什么第一种方法不起作用。
+(...)
是扩展的 glob 语法,您需要启用 extglob
特性才能让 bash 理解它。并且如 中所述,通常不应使用抑扬符来否定字符 class。 Bash 容忍这个错误,但无论如何为了可移植性让我们使用正确的语法:
shopt -s extglob
p="folderA/folderB/folderC"
echo "${p%%+([!/])}"
echo "${p#${p%%+([!/])}}"
产量:
folderA/folderB/
folderC
相关link:Bash Reference Manual § Pattern Matching。
顺便说一句,你真的不需要为此扩展 glob。
p="folderA/folderB/folderC"
echo "${p%${p##*/}}"
echo "${p##*/}"
以上脚本在任何符合 POSIX 的 shell.
上同样有效
另一个更符合标准的 Korn shell 实际上输出
folderA/folderB/folderC
后跟一个空行。这是因为 shell glob 是 不是 正则表达式,字符 class 协商运算符是一个假朋友。
在POSIX shell中,[^/]
is actually unspecified但通常(["^"/]
更清楚)表示“^
或/
”,但你会想要“任何不是 /
的东西”,在 POSIX shell glob 中,它是 [!/]
。
有关 GNU bash 如何需要 shopt -s extglob
支持 Korn shell 兼容的扩展 globbing 模式的解释,请参阅 。
为什么以下代码在 ksh 和 bash
中产生不同的输出p="folderA/folderB/folderC"
echo ${p%%+([^/])}
echo ${p#${p%%+([^/])}}
ksh 输出:
folderA/folderB/
folderC
bash 输出:
folderA/folderB/folderC
我特别困惑,因为我使用 bash documentation 创建了这个参数扩展。
我想提取最后一个斜杠后的文件夹名称。我找到了另一种在 ksh 和 bash:
中工作的方法echo ${p##*/}
但我想了解为什么第一种方法不起作用。
+(...)
是扩展的 glob 语法,您需要启用 extglob
特性才能让 bash 理解它。并且如
shopt -s extglob
p="folderA/folderB/folderC"
echo "${p%%+([!/])}"
echo "${p#${p%%+([!/])}}"
产量:
folderA/folderB/
folderC
相关link:Bash Reference Manual § Pattern Matching。
顺便说一句,你真的不需要为此扩展 glob。
p="folderA/folderB/folderC"
echo "${p%${p##*/}}"
echo "${p##*/}"
以上脚本在任何符合 POSIX 的 shell.
上同样有效另一个更符合标准的 Korn shell 实际上输出
folderA/folderB/folderC
后跟一个空行。这是因为 shell glob 是 不是 正则表达式,字符 class 协商运算符是一个假朋友。
在POSIX shell中,[^/]
is actually unspecified但通常(["^"/]
更清楚)表示“^
或/
”,但你会想要“任何不是 /
的东西”,在 POSIX shell glob 中,它是 [!/]
。
有关 GNU bash 如何需要 shopt -s extglob
支持 Korn shell 兼容的扩展 globbing 模式的解释,请参阅