당신은 다음과 같이 할 수 있습니다 :
cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/ ${PWD%/*}
printf %s\\n "${PWD##*/}"
/u/s/m/man1
그리고 여기에 sed
:
printf %s "$file" |
tr /\\n \\n/ | sed -et$ \
-e '\|^\.\.$|{x;s|\(.*\)\n.*$|\1|;x;}' \
-e 's|^\.\{0,2\}$||;\|.|H;$!d;x' \
-e$ -e '\|\(\.\{0,2\}.\)\(.*\)\(\n\)|!b' \
-e 's||\1\3\2\3|;P;s|\n||;D' |
tr /\\n \\n/
그것은 함수가 아래에서하는 것과 똑같은 일을하는 것과 아주 가깝습니다. $PWD
함수가하는 것처럼 슬래시로 머리 글자를 생략하거나 머리에 삽입하여 슬래시를 선행하지 않습니다 (실제로 슬래시를 인쇄하지 않음). 그러나 나중에 처리 할 수 있습니다. 널 (null) 경로 구성 요소 및 단일 도트를 처리하고 ..
케이스를 제거합니다.
위와 같은 man
경로가 주어지면 다음과 cd
같이 인쇄됩니다.
u/s/m/man1
또한 시작점으로 시작하고 하나 또는 두 개의 점이 아닌 각 경로 구성 요소에 대해 하나 또는 두 개의 추가 선행 점을 인쇄합니다.
로 시작하는 경로 구성 요소에 대해 두 개 이상의 문자를 수행하는 방법에 대해 질문했습니다 .
. 그것을하기 위해 나는 어쨌든 각각의 구성 요소가 개별적인주의를 필요로한다고 생각했고, 궁금해서 변경 디렉토리없이 정식 경로를 만드는 데 손을 댔다. 시행 착오 후에 나는 그것을 올바르게하는 유일한 방법은 그것을 앞뒤로 두 번하는 것이라고 결정했습니다.
pathbytes(){
local IFS=/ o="$-" p
set -f${ZSH_VERSION+LFy}
set -- ${1:-$PWD}
for p in /${1:+$PWD} $*
do case $p in (.|"") ;;
(..) ${1+shift} ;;
(/) set -- ;;
(*) set -- $p $*; esac
done
for p in //$* ""
do case ${p:-/$3} in
([!./]*) ;;
(..*) set "..$@" ;;
(.*) set ".$@" ;;
(//*) ! set "" $1 $1 ;;
(~) ! p=\~ ;;
(~/*) p="~/$2";set $HOME
! while "${2+shift}" 2>&3
do p="~/${p#??*/}"
done 3>/dev/null;;
esac&& set "" "${p%"${p#$1?}"}/$2" "$p/$3"
done; printf %s\\n "${p:-$2}"
set +f "-${o:--}"
}
따라서 디렉토리를 변경하지 않거나 경로 구성 요소의 존재를 확인하려고 시도하지만 반복되는 /
구분 기호를 누르고 /./
단일 도트 구성 요소를 완전히 삭제 하고 /../
이중 도트 구성 요소를 적절하게 처리합니다.
공백이 아닌 문자$IFS
로 설정된 경우 , 두 개 이상의 문자 시퀀스는 하나 이상의 널 (null) 필드가됩니다. 따라서 여러 개의 연속 슬래시는 널값 인수로 해결됩니다. 주인공도 마찬가지입니다 . 분할 할 때 결과 가 null 인 경우 슬래시로 시작하고 null이 아닌 경우 i 삽입 합니다. 즉, 첫 번째 인수가 슬래시로 시작하지 않으면 앞에 추가됩니다. 이것이 경로 유효성 검사 와 관련이 있습니다.$IFS
$IFS
set -- $1
$1
${1:+$PWD}
$PWD
$PWD
그렇지 않으면 첫 번째 for
루프는 다음과 같이 경로 구성 요소의 순서를 재귀 적으로 반전시킵니다.
1 2 3
1 2 3
2 1 3
3 2 1
... 그렇게하는 동안 단일 점 또는 null 구성 요소를 무시하고 그렇게합니다 ..
...
1 .. 3
1 .. 3
3
3
... 두 번째 패스는이 효과를 반대로하고, 그렇게하는 동안 각 구성 요소를 2-dots + char 또는 1-dot + char 또는 char로 압착합니다 .
존재 여부에 관계없이 표준 경로로 작동해야합니다.
두 번째 루프에 약간 더하거나 뺍니다. 이제는 set
빈도가 줄어들고 (각 [!./]*
구성 요소 에 대해 한 번만 ) , case
대부분의 경우 회로 패턴 평가 (앞서 언급 한 패턴 덕분에)를 단락 시키고에 대한 테일 콜 매치 평가를 포함 ~
합니다. 최종 정식 경로의 전체 또는 선행 부분 (전체 구성 요소로 나눈 값) 이 일치 할 수 있으면 일치 ~
하는 비트가 제거되고 리터럴 ~
이 대체됩니다. 이렇게하려면 약어와 함께 경로의 전체 사본을 유지해야했습니다 (약어 경로를 일치시키는 ~
것이별로 도움이되지 않기 때문에) . 그래서 이것은 유지됩니다 $3
. 마지막while
루프 분기는 ~
의 하위 집합과 일치 하는 경우에만 실행됩니다 $3
.
set -x
추적 기능을 사용 하여 실행하면 작동하는 것을 볼 수 있습니다.
$ (set -x;pathbytes ..abc/def/123///././//.././../.xzy/mno)
+ pathbytes ..abc/def/123///././//.././../.xzy/mno
+ local IFS=/ o=xsmi p
+ set -f
+ set -- ..abc def 123 . . .. . .. .xzy mno
+ set --
+ set -- home
+ set -- mikeserv home
+ set -- ..abc mikeserv home
+ set -- def ..abc mikeserv home
+ set -- 123 def ..abc mikeserv home
+ shift
+ shift
+ set -- .xzy ..abc mikeserv home
+ set -- mno .xzy ..abc mikeserv home
+ set mno mno
+ set . mno mno
+ set .x/mno .xzy/mno
+ set .. .x/mno .xzy/mno
+ set ..a/.x/mno ..abc/.xzy/mno
+ set m/..a/.x/mno mikeserv/..abc/.xzy/mno
+ set h/m/..a/.x/mno home/mikeserv/..abc/.xzy/mno
+ p=~/h/m/..a/.x/mno
+ set home mikeserv
+ shift
+ p=~/m/..a/.x/mno
+ shift
+ p=~/..a/.x/mno
+
+ printf %s\n ~/..a/.x/mno
~/..a/.x/mno
+ set +f -xsmi
/f/b/.c/wizard_magic
. 점은 종종 특정 디렉토리에서 매우 일반적이므로 찾고있는 곳의 아주 작은 단서가됩니다.