Ви можете це зробити так:
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
голову для провідного не-косого кута, як це робить функція (і насправді ніколи не друкує провідну косу рису), але з цим можна було б звертатися згодом. він обробляє нульові компоненти контуру, одинарні крапки та ..
випадки бур’янів .
заданий той самий man
шлях, cd
що і надрукований над ним:
u/s/m/man1
він також надрукує одну або дві додаткові провідні точки для кожного компонента шляху, який починається з такого, і не є лише однією або двома крапками.
ви запитували про те, як зробити більше одного символу для компонента шляху, що починається з "a" .
. для цього я зрозумів, що кожен компонент так чи інакше потребує індивідуальної уваги, і тому, що мені було цікаво, я спробував свої сили в розробці канонічного шляху без каталогу змін. після деяких проб і помилок я врешті вирішив, що єдиний спосіб зробити це правильно - це зробити два рази - назад і вперед:
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
встановлено якийсь символ, який не є пробілом , послідовність двох або більше $IFS
символів призведе до одного або декількох нульових полів. тож декілька послідовних косої риски працюють з нульовими аргументами. те саме стосується і провідного $IFS
персонажа. і тому, коли set -- $1
розбивається, якщо результат $1
є нульовим, тоді він починався з косою рисою, інакше, ${1:+$PWD}
якщо він не є null, то я вставляю $PWD
. Іншими словами, якщо перший аргумент не починається з косої риски, він буде попередньо $PWD
висунутий. це так само близько, як це стосується перевірки шляху .
в іншому випадку перший for
цикл рекурсивно інвертує порядок компонентів шляху, наприклад:
1 2 3
1 2 3
2 1 3
3 2 1
... при цьому він ігнорує будь-які одноточкові або нульові компоненти, і для ..
цього робить ...
1 .. 3
1 .. 3
3
3
... другий пропуск обертає цей ефект, і, роблячи це, він видавлює кожен компонент або на 2 крапки + char , або на 1 крапки + 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
. Крапка часто настільки поширена в певному каталозі, що є дуже маленькою підказкою того, куди ви повинні шукати.