如何从 Bash 中的字符串中去除或替换模式的所有匹配项?

How to strip or replace all matches of a pattern from a string in Bash?

我正在尝试在 Bash 中编写 dirname 函数,这样它就不会使用任何外部命令。

function dirname() {
  local path=
  [[ $path =~ ^[^/]+$ ]] && dir=. || {              # if path has no slashes, set dir to .
    [[ $path =~ ^/+$ ]]  && dir=/ || {              # if path has only slashes, set dir to /
      local IFS=/ dir_a i
      read -ra dir_a <<< "$path"                    # read the components of path into an array
      dir="${dir_a[0]}"
      for ((i=1; i < ${#dir_a[@]}; i++)); do        # strip out any repeating slashes
        [[ ${dir_a[i]} ]] && dir="$dir/${dir_a[i]}" # append unless it is an empty element
      done
    }
  }

  [[ $dir ]] && printf '%s\n' "$dir"                # print only if not empty
}

为了从路径中删除任何重复的 /,我不得不使用数组逻辑。有没有更简单的方法来对 Bash Parameter Expansion 做同样的事情?我试过了,但我好像不太对劲。

基本上,我想将所有出现的多个连续斜杠分别替换为一个斜杠。

如果 extglob 开启:

shopt -s extglob

你可以这样做:

printf '%s\n' "${path//\/+(\/)/\/}"

这使用 ${var//pattern/replacement} 语法进行全局替换。

模式是 \/+(\/)(带有转义斜杠,因为 / 是定界符),实际上是 /+(/)(其中 +(/) 表示 "one or more slashes") .