Dizin hesaplama


19

Bu meydan okuma için, mutlak bir yol ve "yeni" bir yol (mutlak veya göreli olabilir) verilecek ve son yolu döndürmeniz gerekecek.

Örneğin, geçerli dizininiz /var/tmp/test:

my_dirya da my_dir/ geri dönmeli/var/tmp/test/my_dir

../../my_dir geri dönmeli /var/my_dir

/my_dir/./ geri dönmeli /my_dir

../../../../../ geri dönmeli /

Daha bilgiç olmak için:

  • Bir dizin alfanümerik karakterden oluşan boş olmayan bir dize ve semboller -, _ya.
  • Yol, kullanılarak ayrılmış 0 veya daha fazla dizin listesidir/ . Mutlak yol a ile başlar /, göreli yol başlamaz. Yollar bir bitiş içerebilir /.

İlk yol verildiğinde, ikinci yolu "çözmeniz" gerekir.

Çözüm süreci:

  1. İkinci yolun göreli olup olmadığını test edin. Öyleyse, mutlak yolun dizinlerini ikinci yolun başına ekleyin.
  2. Dizinlerden herhangi biri varsa, dizini ..ve önceki dizini kaldırın. İlk dizinse, kaldırın.
  3. Dizinlerden herhangi biri varsa ., kaldırın.
  4. Son mutlak yolu çıktılayın. Bir son vermemelisiniz /.

Yanlış girişi işlemenize gerek yoktur. Gönderilen dizinler makinenizde mevcut olsa da olmasa da komutlar çalışmalıdır. Bir uzantıya sahip olsa bile her şeyin bir dizin olduğunu varsayabilirsiniz.

Test senaryoları

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"
"/."          ""        -> "/"

Bu bir , bu yüzden gönderilerinizi en sevdiğiniz dilde mümkün olduğunca kısa yapın!


Bazı yanıtlar varsaymak görünen dosyaları yok) dizin ağacının herhangi bir bölümünde aynı adı taşıyan (veya sembolik) değil makinede mevcuttur. Buna izin veriliyor mu?
Dennis

İki girişi istediğimiz sırayla alabilir miyiz?
Haziran

Aptalca bir soru ... yan etkileri olabilir mi? Özellikle, um, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(veya bir şey) gibi yan etkiler ?
kedi

@dennis. Programların çıktıları dosya sisteminden bağımsız olmalıdır
Nathan Merrill

@downgoat iyi
Nathan Merrill

Yanıtlar:


7

Retina , 44 bayt

+`.+ /| |/\.?/
/
+1`/?[^/]*/\.\.|/\.?$

^$
/

Girdinin tek bir boşlukla ayrılmış iki yol olması beklenir.

Çevrimiçi deneyin! (İlk satır, satır besleme ile ayrılmış bir test paketini etkinleştirir.)


3

Python, 53 bayt

from os.path import*;p=lambda a,n:normpath(join(a,n))

3

Toplu, 282 281 279 276 bayt

@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

Sıkıcı bir şekilde Toplu ifadeler genellikle boş değişkenleri sevmez. Düzenleme: @ CᴏɴᴏʀO'Bʀɪᴇɴ sayesinde 1 bayt ve @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ sayesinde 2 bayt (ve ne yazık ki uncredited olmasına rağmen, diğer cevaplarda da bir bayt) kaydedildi.


Sanırım callve: x` arasındaki boşluğu kaldırabilirsiniz , değil mi?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, böylece yapabilirsiniz. Bu durumda güncellenmesi gereken bir sürü
Neil

2

Python 2, 265 260 254 bayt

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, 142137 bayt

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

Bash, 41 bayt

Bu bash betiği, yoksa dizin oluşturma yan etkisine sahiptir, ancak gereksinimleri karşılamalıdır. İyileştirmeleriniz için Karl ve Neil'e teşekkür ederiz .

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

Kullanım: bash getpath.sh "mutlak" "yeni"

İkinci argüman boş bir dize olduğunda stderr'i beğenmezseniz, bunu aşağıdaki gibi test edebilirsiniz (48 bayt):

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

Önceki 30 bayt girişimi (dizinlerin var olmasını gerektirir): cd $ 1; [$ 2] && cd $ 2; echopwd


Soru , makinenizde geçen dizinlerin gerçekten var olup olmadığına bakılmaksızın, komutların çalışması gerektiğini
Dennis

Ah, anlıyorum. Çok kötü.
Bryn

Merhaba, PPCG'ye hoş geldiniz! Normalde, cevabınız işe yaramazsa, silmiş olursunuz. Bu yorumun üstündeki sil bağlantısını tıklayabilirsiniz.
NoOneIsHere

mkdir -pOnların varolduğundan emin olabilirsiniz .
Karl Napf

Teşekkürler, mkdir ile bir sürüm deniyorum. Bu cevabı sileceğim ve çözersem yeni bir cevap ekleyeceğim.
Bryn

1

C #, 43 bayt

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

@Aloisdg sayesinde 1 bayt kaydedildi

Path.Combineargümanları bir araya getirir Path.GetFullPathve ..\s


Merhaba, PPCG'ye hoş geldiniz! Bu geçerli bir program değil - ya mainbir sınıf ve bir sınıf ya da bir lanbda olarak değiştirin: a,b->...
NoOneIsHere

Ben göndermek için gidiyordu :) Güzel ilk teslim! Eğer sonra boşluk kaldırabilirsiniz ,: (x, y)=>(x,y)
aloisdg diyor eski durumuna Monica



1

Javascript, 210 bayt

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)}

İşte test takımı

Noktalı virgül yerine satır sonu işaretleriyle:

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 bayt

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

normalizegöreli referanslarla başa çıkmak için gereklidir. addile başlayan ikinci yolu işlemek için kullanılır /ki, Paths.get(a, b)belirtilen bir işlem yapılmayacaktır.


Merhaba, PPCG'ye hoş geldiniz! Bu iyi bir ilk gönderi!
NoOneIsHere

0

Bash, 38 bayt

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

Kök ayrıcalıkları gerektirmez ve var olan veya var olmayan dosyalar, dizinler veya sembolik bağlantılar hakkında hiçbir varsayımda bulunmaz.

Ideone üzerinde test edin .

Nasıl çalışır

[[ $2 = /* ]]ikinci komut satırı argümanının başlayıp başlamadığını test eder /.

Değilse, yol görecelidir ve pp=$1 değişkenini ilk komut satırı bağımsız değişkenine ayarlar .

Bu yol $p/$2, /$2eğer $2mutlak bir yol ve $1/$2gerçek bir yolsa.

Son olarak, realpath -sm $p/$2kurallı mutlak yolunu yazdırır $p/$2. -sAnahtar markaları realpath sembolik bağlantıları görmezden ve -manahtar kayıp bileşenler.


0

Ruby, 16 bayt

Görünüşe göre standart kütüphaneden bir yöntem kullanılmasına izin verildiğinden:

File.expand_path

Repl.it adresindeki test paketine bakın .


Değişkenler aracılığıyla girişe izin verilmez, ancak işlev gönderimi, yani kısaltmanız gerektiği anlamına gelir File.expand_path:)
Nathan Merrill

Ayrıca, tüm test senaryolarında doğru çalıştığından emin olmak için test takımına karşı test etmenizi de öneririm.
Nathan Merrill

@NathanMerrill Yaptım, ama devam edip repl.it'e bir şey yapıştıracağım.
Ürdün

Test paketi bağlantısını içerecek şekilde düzenlendi.
Ürdün

0

GNU sed , 81 59 + 1 = 60 bayt

-rBayrak için +1 bayt . STDIN üzerindeki girdinin tek bir boşlukla ayrılmasını bekler.

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

Çevrimiçi deneyin!

açıklama

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.