在以下函数的上下文中
function foo { local d="d"; printf "%s" "${@/#/$d}"; }
这是什么/#/
意思?
当我调用它时foo a b c
它返回dadbdc
。
答案1
在你的代码中/#/
属于"${@/#/$d}"
。这是关于什么参数扩展可以在 Bash 中执行。
${parameter/pattern/string}
被pattern
扩展以产生一个模式,就像文件名扩展一样。被扩展并且与其值parameter
的最长匹配被替换为。[…] 如果以开头,它必须与扩展值的开头匹配。[…]pattern
string
pattern
#
parameter
#
aspattern
应解释为以#
开头为锚点,加上一个空字符串作为实际要匹配的模式。它匹配开头的一个空字符串。
string
本身会经历参数扩展(尽管引用的片段没有明确说明这一点)。在您的代码中$d
扩展为d
。
如果是${parameter/#/$d}
,d
则会在 的扩展值开头替换一个空字符串parameter
。换句话说,d
将在扩展值前面加上前缀。这适用于parameter
保留空字符串的情况(结果将只是d
),但不适用于parameter
未设置的情况(结果仍为空,就像任何未设置的参数一样,d
不会被添加)。
在您的代码中, 代替@
。parameter
Simple$@
扩展为从 1 开始的所有位置参数(如果第一个参数未设置,则扩展为零)。"$@"
扩展为所有位置参数,其中每个位置参数的行为都像单独用双引号引起来一样。 同样地,${@/#/d}
扩展为所有位置参数,其中每个位置参数都位于d
前面;并且如果$d
扩展为d
,${@/#/$d}
则会给出相同的结果。 最后"${@/#/$d}"
扩展为所有位置参数,其中每个位置参数都位于d
前面并且行为都像单独用双引号引起来一样。
因此,当你运行foo a b c
,printf "%s" "${@/#/$d}"
相当于
printf "%s" "da" "db" "dc"
注意${parameter/pattern/string}
语法是不是指定POSIX。
答案2
"${@/#/$d}"
由 Bash 以下列方式扩展:
@
foo
指的是参数数组,因此如果你调用类似的函数foo "a b" c
,那么参数数组有两个条目a b
和c
。"${varname/pattern/replacement}"
(模式替换)用替换pattern
变量中的第一个实例。varname
replacement
#
在模式替换中匹配变量值的开头而不是文字字符串“#”。$d
是一个简单的变量引用,并且会扩展为变量的值d
。
总之,这将扩展到每个函数参数,然后在每个参数之前插入变量的值d
。 这些参数中的每一个都以无格式(重要的是没有分隔符)的方式打印printf
。
这个函数的一个好名字可能是prefix_join
,因为它基本上为每个参数加上前缀,然后将它们连接起来。