2017-10-18 73 views
2

我想在Bash中编写dirname函数,以便它不使用任何外部命令。如何从Bash中的字符串中删除或替换所有模式的匹配项?

function dirname() { 
    local path=$1 
    [[ $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?我试过了,但我似乎没有把握好。

基本上,我想用单斜杠替换所有出现的多个连续的斜杠。

+0

'echo“$ {path%\/*}”'? – Cyrus

+0

这将只删除最后一个'/'向前。例如:如果path是'a // b // c /// d',它会给我们'a // b // c //'。 – codeforester

+0

只是出于好奇,你在哪里找到像'a // b // c /// d'这样的路径?我唯一遇到的问题是用'drive:\\ a \\ b \\ c \\ file.ext'将其转换为POSIX驱动器:/a/b/c/file.ext '。你在哪里可以创建一个像“a // b // c /// d'这样的路径? windoze?或者,这只是一个通用的*多个''//'' *练习? –

回答

4

如果extglob是:

shopt -s extglob 

,你可以这样做:

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

它使用${var//pattern/replacement}语法做全局替换。

的图案是\/+(\/)(带斜线转义因为/是分隔符),这是真的/+(/)(其中+(/)装置“的一个或多个斜线”)。

相关问题