Справочник расчета


19

Для этого испытания вам будет предоставлен абсолютный путь и «новый» путь (который может быть абсолютным или относительным), и вам нужно будет вернуть окончательный путь.

Например, если ваш текущий каталог был /var/tmp/test:

my_dirили my_dir/ должен вернуться/var/tmp/test/my_dir

../../my_dir должен вернуться /var/my_dir

/my_dir/./ должен вернуться /my_dir

../../../../../ должен вернуться /

Чтобы быть более педантичным:

  • Каталог является непустая строка , состоящая из буквенно - цифровых символов и символов -, _или.
  • Путь - это список из 0 или более каталогов , разделенных с помощью /. Абсолютный путь начинается с a /, относительный путь - нет. Пути могут включать окончание /.

Вам необходимо «разрешить» второй путь, учитывая первый путь.

Процесс разрешения:

  1. Проверьте, является ли второй путь относительным. Если это так, вставьте каталоги абсолютного пути в начало второго пути.
  2. Если какой-либо из каталогов есть .., то удалите его и предыдущий каталог. Если это первый каталог, просто удалите его.
  3. Если какой-либо из каталогов есть ., то удалите его.
  4. Выведите окончательный абсолютный путь. Вы не должны выводить окончание /.

Вам не нужно обрабатывать неправильный ввод. Команды должны работать независимо от того, существуют ли фактически переданные каталоги на вашем компьютере. Вы можете предположить, что все является каталогом, даже если он имеет расширение.

Контрольные примеры

Absolute      New          Output
"/a/b/c"      "d"       -> "/a/b/c/d" 
"/a/b/c/"     "d"       -> "/a/b/c/d"
"/a/b/c/"     "d/"      -> "/a/b/c/d"
"/a/b/c"      "/d"      -> "/d"
"/a/b/c"      "/d/"     -> "/d"
"/../a/b/c/"  "d"       -> "/a/b/c/d"
"/a/../b/c/"  "d"       -> "/b/c/d"
"/a/b/../c"   "d"       -> "/a/c/d"
"/a/b/c/.."   "d"       -> "/a/b/d"
"/a/b/c/"     ".."      -> "/a/b"
"/a/b/c"      "../d"    -> "/a/b/d"
"/a/b/c"      "/../d"   -> "/d"
"/a/b/c"      ""        -> "/a/b/c"
"/a/b/c"      "."       -> "/a/b/c"
"/a/b/c"      "./d"     -> "/a/b/c/d"
"/a/b/c"      "/./d"    -> "/d"
"/a/b/c"      "d.txt"   -> "/a/b/c/d.txt"
"/a/b/c"      "d."      -> "/a/b/c/d."
"/a/b/c"      ".txt"    -> "/a/b/c/.txt"
"/a/b/c"      ".txt/d"  -> "/a/b/c/.txt/d"
"/a/b/."      "./././." -> "/a/b"
"/direc"      "tory"    -> "/direc/tory"
"/a-_.b/"     "__._-."  -> "/a-_.b/__._-."
"/a/b"        "../.."   -> "/"
"/a/b"        "../../.."-> "/"
"/a"          "../../.."-> "/"
"/"           ""        -> "/"
"/"           "a"       -> "/a"
"/.."         "a"       -> "/a"
"/."          ""        -> "/"

Это , поэтому делайте ваши заявки как можно короче на вашем любимом языке!


Некоторые ответы предполагают, что файлы (или символические ссылки) с тем же именем, что и любая часть дерева каталогов) не существуют на компьютере. Это разрешено?
Деннис

Можем ли мы взять два входа в любом порядке, который пожелаем?
Downgoat

Глупый вопрос ... Могу ли я иметь побочные эффекты? В частности, побочные эффекты, например, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(или что-то)?
кот

@dennis. Вывод программ должен быть независимым от файловой системы
Натан Меррилл

@ Downgoat, это хорошо
Натан Меррилл

Ответы:




3

Пакет, 282 281 279 276 байт

@echo off
set a=\
set r=%~2
if "%r%"=="" set r=%~1
if not %r:~,1%==/ set r=%~1/%~2
for %%a in (%r:/= %)do call:x %%a
if not %a%==\ set a=%a:~,-1%
echo %a:\=/%
exit/b
:x
if %1==. exit/b
if not %1==.. set a=%a%%1\&exit/b
if not %a%==\ for %%a in (%a:~,-1%)do set a=%%~pa

Досадно, что пакетные выражения обычно не любят пустые переменные. Редактировать: 1 байт благодаря @ CᴏɴᴏʀO'Bʀɪᴇɴ и 2 байта благодаря @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (и куча байтов на других ответах, хотя, увы, не зачислены).


Я думаю, что вы можете удалить пробел между callи: x`, нет?
Конор О'Брайен

@ C'O'Bʀɪᴇɴ Да, так что ты можешь. У меня есть куча ответов, которые нужно обновить в этом случае ...
Нил

2

Python 2, 265, 260, 254 байта

y=lambda:[x for x in raw_input().split("/")if x!=""and x!="."]
a=y();n=y();m=len(a)-1
while m>0:
 if a[m]==".."and m>0:del a[m];del a[m-1];m-=1
 elif a[m]=="..":del a[m]
 m-=1
for i in n:
 if i==".."and len(a)>0:del a[-1]
 else:a+=i,
print"/"+"/".join(a)

1

Python, 142 137 байт

def p(a,n,r=[],S="/"):
 for s in[s for s in((n[:1]!=S)*a+S+n).split(S)if"."!=s and s]:e=s!="..";r=[s]*e+r[1-e:]
 return S+S.join(r[::-1])

1

Баш, 41 байт

Этот скрипт bash имеет побочный эффект создания каталогов, если они не существуют, но он должен соответствовать требованиям. Спасибо Карлу и Нилу за ваши улучшения.

mkdir -p $1;cd $1;mkdir -p $2;cd "$2";pwd

Использование: bash getpath.sh "absolute" "new"

Если вам не нравится stderr, когда второй аргумент является пустой строкой, вы можете проверить его следующим образом (48 байт):

mkdir -p $1;cd $1;[ $2 ]&&mkdir -p $2&&cd $2;pwd

Предыдущая 30-байтовая попытка (требуется наличие каталогов): cd $ 1; [$ 2] && cd $ 2; echopwd


В вопросе говорится, что команды должны работать независимо от того, существуют ли фактически переданные каталоги на вашем компьютере.
Деннис

Ах я вижу. Печалька.
Брин

Здравствуйте и добро пожаловать в PPCG! Обычно, если ваш ответ не работает, вы удаляете его. Вы можете нажать на ссылку удаления над этим комментарием.
NoOneIsHere

Вы могли mkdir -pбы убедиться, что они существуют.
Карл Напф

Спасибо, я пробую версию с mkdir. Я удалю этот ответ и добавлю новый, если выясню.
Брин

1

C #, 43 байта

(x,y)=>Path.GetFullPath(Path.Combine(x,y));

Сохранено 1 байт благодаря @aloisdg

Path.CombineПереводит аргументы вместе, и Path.GetFullPathрешает , что ..\ы


Здравствуйте и добро пожаловать в PPCG! Это недопустимая программа - либо mainвключите и класс, либо измените его на lanbda: a,b->...
NoOneIsHere

Я собирался опубликовать его :) Хорошая первая подача! Вы можете удалить пробел после ,: (x, y)=>(x,y)
aloisdg говорит Восстановить Монику



1

Javascript, 210 байт

function p(a,b){d='.';e=d+d;s='/';t='split';u='splice';r=(b[0]===s?[]:a[t](s)).concat(b[t](s));for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)(!r[i]||r[i]===d)&&r[u](i,1)&&i--;return s+r.join(s)}

Вот тестовый набор

С переносами строк вместо точек с запятой:

function p(a,b) {
    d='.'
    e=d+d
    s='/'
    t='split'
    u='splice'

    r=(b[0]===s?[]:a[t](s)).concat(b[t](s))

    for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)
        (!r[i]||r[i]===d)&&r[u](i,1)&&i--

    return s+r.join(s)
}

0

Java 7, 83 байта

String p(String a,String b){return Paths.get(a).resolve(b).normalize().toString();}

normalizeнеобходимо иметь дело с относительными ссылками. addиспользуется для обработки второго пути, начинающегося с /, который Paths.get(a, b)не будет обрабатываться как указано.


Здравствуйте и добро пожаловать в PPCG! Это хороший первый пост!
NoOneIsHere

0

Баш, 38 байт

[[ $2 = /* ]]||p=$1
realpath -sm $p/$2

Не требует прав суперпользователя и не делает никаких предположений о существующих или несуществующих файлах, каталогах или символических ссылках.

Проверьте это на Ideone .

Как это устроено

[[ $2 = /* ]]тесты , если второй аргумент командной строки начинается с /.

Если это не так, путь является относительным и p=$1устанавливает переменную p в качестве первого аргумента командной строки.

Этот путь $p/$2, /$2если $2это абсолютный путь, и $1/$2если он реальный.

Наконец, realpath -sm $p/$2печатает канонический абсолютный путь $p/$2. В -sкоммутаторе марка Realpath игнорирует символические ссылки, а также -mпереключатель отсутствует компоненты.


0

Рубин, 16 байт

Поскольку, очевидно, использование метода из стандартной библиотеки разрешено:

File.expand_path

Смотрите набор тестов на repl.it .


Ввод через переменные не разрешен, но отправка функции, это означает, что вы должны сократить его до File.expand_path:)
Натан Меррилл

Я также рекомендовал бы на самом деле протестировать его с помощью набора тестов, чтобы убедиться, что он работает корректно во всех тестовых случаях.
Натан Меррилл

@NathanMerrill Я сделал, но я продолжу и вставлю кое-что на repl.it.
Иордания

Отредактировано, чтобы включить ссылку на набор тестов.
Иордания

0

GNU sed , 81 59 + 1 = 60 байт

+1 байт за -rфлаг. Ожидается, что ввод в STDIN отделяется одним пробелом.

s:.+ /::
s:/? :/:
:
s:/$|[^/]+/+\.\.|\.(/|$):\1:
t
s:^/*:/:

Попробуйте онлайн!

объяснение

s:.+ /::  # If the second argument starts with a slash, drop the first argument
s:/? :/:  # Join the first and second arguments with a slash, dropping duplicate slashes
:
  s:/$|[^/]+/+\.\.|\.(/|$):\1:  # Drop trailing slashes, resolve double and single dots
  t                             # If the above substitution was made, branch to :
s:^/*:/:  # Ensure output begins with a single slash

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.