星号的作用凭什么不断变化?
CASE 1:
var1=abcd-1234-defg
echo ${var1#*-*} # RESULT: 1234-defg
CASE 2:
stringZ=abcABC123ABCabc
echo `expr match "$stringZ" '\(abc[A-Z]*.2\)'` # RESULT: abcABC12
星号的作用何时以及如何决定?
CASE 3:
path_name="/home/bozo/ideas/thoughts.for.today"
echo ${path_name##/*/} # RESULT : thoughts.for.today
在这种情况下,我误认为/
在这里扮演了逃避角色的角色,即试图逃避 的基本特征*
。好吧,我错了。那么这些特殊角色的角色是如何决定的、由谁决定的呢?
CASE 4:
var1=abcd--1234-defg
echo ${var1#*-*} # RESULT: -1234-defg & i was expecting 1234-defg
CASE 4 与 CASE 1 类似,但可以看出有所不同abcd--
,我也在预料之中1234-defg
,但结果却与 CASE 1 相同。
*-*
我对案例4的解释是这样的:
shell 会查找从 var1 开头开始的所有内容,直到找到 - OR -- OR ---
为什么我对案例 4 的解释不正确?
答案1
那是因为*
在您的测试中具有不同的含义。
在情况1,案例3和案例4,它用作模式匹配。而在案例2, 它是正则表达式元字符(或量词或克林星)。
在模式匹配中,*
字符将匹配任何字符串,包括空字符串,a*
将匹配任何以a
, example a
, aa
,开头的字符串ab
,但不匹配b
在正则表达式中,*
量词匹配零个或多个前面的标记,a*
将匹配零个或多个a
序列,例如''
, a
, aa
, aaa
, ab
, b
。
考虑到这些,您的案例4将被解释为匹配任何包含的字符串-
,因为它被用作模式匹配,所以您所讨论的解释被用作正则表达式。
因此abcd--1234-defg
,最短的子字符串匹配*-*
是abcd-
,最长的匹配是整个字符串。因为当您使用表单时${var1#*-*}
,这是一个参数扩展$var1
要删除match中的最短前缀*-*
,您可以得到-1234-defg
,因为匹配的最短前缀是abcd-
。
答案2
有两点需要理解:
在一个 glob 中,
*
匹配零个或多个任何字符的该表格
${var1#*-*}
删除了最短匹配。
因此,${var1#*-*}
只会删除第一个破折号,因为这是最短匹配。
为了完整起见,注释${var1##*-*}
将删除最长的匹配项。
例子
在下面的每种情况下,最短匹配的前缀被删除:
$ var1=abcd-1234-defg
$ echo ${var1#*}
abcd-1234-defg
$ echo ${var1#*-}
1234-defg
$ echo ${var1#*-*}
1234-defg
$ echo ${var1#*-*-}
defg
$ echo ${var1#*-*-*}
defg
将上面的情况与##
删除的情况进行对比最长匹配前缀:
$ echo ${var1##*-}
defg
$ echo ${var1##*-*}
$
文档
从man bash
:
${parameter#word} ${parameter##word}
删除匹配的前缀模式。该单词被扩展以产生一个模式,就像路径名扩展一样。如果模式与参数值的开头匹配,则扩展的结果是扩展后的参数值 最短匹配模式(
#
案例)或最长的匹配模式(##
案例)已删除。如果参数是@或*,则依次对每个位置参数应用模式删除操作,并且扩展是结果列表。如果parameter是下标为@或*的数组变量,则模式删除操作将依次应用于数组的每个成员,并且扩展是结果列表。 [强调。]