我已经阅读了GNU 的“Shell Parameter Expansion”文档,给出了以下语法:
${parameter//pattern/string}
该模式被扩展以产生一个模式,就像在文件名扩展中一样。参数被扩展,模式 与其值的最长匹配被替换为字符串......如果有两个斜杠分隔参数和模式......,所有匹配的模式都被替换为字符串。
鉴于上面的短语“模式的所有匹配项都替换为字符串”,我希望在一个操作中一次将模式的多个实例全部替换为字符串 ,类似于标志如何与全局搜索和替换一起使用正则表达式中的命令。/g
我有一段开源代码(一个名为 的函数remove_from_path
),其实现如下:
remove_from_path() {
local path_to_remove="$1"
local path_before
local result=":${PATH//\~/$HOME}:"
local counter=0
while [ "$path_before" != "$result" ]; do
counter+=1
echo "counter: $counter"
path_before="$result"
result="${result//:$path_to_remove:/:}"
done
result="${result%:}"
echo "${result#:}"
}
原始代码不包含该变量——我添加了该变量以检查循环将执行counter
多少次迭代。while
正如我们所看到的,该行result="${result//:$path_to_remove:/:}"
使用了 GNU 文档中提到的相同的双正斜杠语法。鉴于此,我希望while
循环只会执行一次,因为path_to_remove
应该result
一次性删除所有实例。
然而,情况似乎并非如此。在bash
shell ( version 3.2.57
) 中,我将 my 更新$PATH
为以下内容:
bash-3.2$ PATH="/foo/bar/baz:/foo/bar/baz:/foo/bar/baz:buzz"
然后我将上述函数复制/粘贴到我的 shell 中,然后运行它。我看到以下内容:
bash-3.2$ remove_from_path "/foo/bar/baz"
counter: 01
counter: 011
counter: 0111
buzz
请忽略计数器的递增没有按我预期的方式工作的事实,因为我们仍然可以看到while
循环的 3 次执行。如果${parameter//pattern/string}
双正斜杠语法确实用字符串替换了所有匹配的模式,为什么没有在循环的一次迭代中完成呢?为什么我们需要 3 次迭代?while