2017-10-18 5 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으로 동일한 작업을 수행하는 간단한 방법이 있습니까? 나는 노력했다, 그러나 나는 그것을 올바르게 얻는 것처럼 보이지 않는다.

기본적으로 여러 개의 연속 된 슬래시가 모두 하나의 슬래시로 바뀝니다.

shopt -s extglob 

당신은이 작업을 수행 할 수 있습니다 :

+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'drive : /a/b/c/file.ext로 바꾸는 것입니다. '. 어디에서'a // b // c /// d'와 같은 경로를 만들 수 있습니까? 바람둥이 요? 아니면, 이것은 단지 일반적인''// ''* 운동을 제거하는 것입니까? –

답변

4

extglob 경우에

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

이 글로벌 대체를 수행 할 ${var//pattern/replacement} 구문을 사용합니다. (/은 구분 기호이기 때문에 탈출 슬래시)

패턴은 정말 인 \/+(\/)입니다 /+(/) (여기서 +(/) 수단 "하나 이상의 슬래시").