هل يمكنني القيام بهذا الأعمى بالنسبة لتحويل المسار المطلق (لمسارات مستودع Perforce) بشكل أفضل؟

StackOverflow https://stackoverflow.com/questions/2836825

سؤال

أحتاج إلى "عمياء" (أي دون الوصول إلى نظام الملفات ، في هذه الحالة خادم التحكم المصدر) يقوم بتحويل بعض المسارات النسبية إلى المسارات المطلقة. لذلك أنا ألعب مع dotdots والمؤشرات. بالنسبة لأولئك الذين يكونون فضوليين ، لدي ملف سجل أنتجته أداة شخص آخر يقوم أحيانًا بإخراج المسارات النسبية ، ولأسباب الأداء ، لا أريد الوصول إلى خادم التحكم في المصدر حيث توجد المسارات للتحقق مما إذا كانت صالحة وأكثر تحويلها بسهولة إلى معادلها المطلق.

لقد مررت بعدد من التكرارات (ربما أحمق) في محاولة لجعلها تعمل - في الغالب بضع أشكال مختلفة من التكرار على مجموعة المجلدات ومحاولة DELETE_AT (الفهرس) و DELETE_AT (INDEX -1) ولكن فهرس الخاص بي استمر في الزيادة أثناء زيادة الفهرس كنت أحذف عناصر الصفيف من تحت نفسي ، والتي لم تنجح في الحالات التي تحتوي على عدة نقاط. أي نصائح حول تحسينه بشكل عام أو على وجه التحديد سيكون عدم وجود دعم DOTDOT غير متتالي.

يعمل هذا حاليًا مع أمثلة محدودة ، لكنني أعتقد أنه يمكن تحسينه. لا يمكن أن تتعامل مع الدلائل غير المتتالية "، وربما أقوم بالكثير من الأشياء المهدرة (والمعرضة للخطأ) التي ربما لا أحتاج إلى القيام بها لأنني مخترق قليلاً.

لقد وجدت الكثير من الأمثلة على تحويل أنواع أخرى من المسارات النسبية باستخدام لغات أخرى ، ولكن يبدو أن أيا منها يناسب وضعي.

هذه هي مسارات مثالي التي أحتاج إلى تحويلها ، من:

//depot/foo/../bar/single.c

//depot/foo/docs/../../other/double.c

//depot/foo/usr/bin/../../../else/more/triple.c

ل:

//depot/bar/single.c

//depot/other/double.c

//depot/else/more/triple.c

ونصي:

begin

paths = File.open(ARGV[0]).readlines

puts(paths)

new_paths = Array.new

paths.each { |path|
  folders = path.split('/')
  if ( folders.include?('..') )
    num_dotdots = 0
    first_dotdot = folders.index('..')
    last_dotdot = folders.rindex('..')
    folders.each { |item|
      if ( item == '..' )
        num_dotdots += 1
      end
    }
    if ( first_dotdot and ( num_dotdots > 0 ) ) # this might be redundant?
      folders.slice!(first_dotdot - num_dotdots..last_dotdot) # dependent on consecutive dotdots only
    end
  end

  folders.map! { |elem| 
    if ( elem !~ /\n/ )
      elem = elem + '/' 
    else
      elem = elem
    end
  }
  new_paths << folders.to_s

}

puts(new_paths)


end
هل كانت مفيدة؟

المحلول

دعونا لا نعيد اختراع العجلة ... File.expand_path هل هذا من أجلك:

[
  '//depot/foo/../bar/single.c',
  '//depot/foo/docs/../../other/double.c',
  '//depot/foo/usr/bin/../../../else/more/triple.c'
].map {|p| File.expand_path(p) }
# ==> ["//depot/bar/single.c", "//depot/other/double.c", "//depot/else/more/triple.c"]

نصائح أخرى

لماذا لا تستخدم فقط File.expand_path:

irb(main):001:0> File.expand_path("//depot/foo/../bar/single.c")
=> "//depot/bar/single.c"
irb(main):002:0> File.expand_path("//depot/foo/docs/../../other/double.c")
=> "//depot/other/double.c"
irb(main):003:0> File.expand_path("//depot/foo/usr/bin/../../../else/more/triple.c")
=> "//depot/else/more/triple.c"

للحصول على حل DIY باستخدام المصفوفات ، يتبادر إلى الذهن (يعمل أيضًا على أمثلةك):

absolute = []
relative = "//depot/foo/usr/bin/../../../else/more/triple.c".split('/')
relative.each { |d| if d == '..' then absolute.pop else absolute.push(d) end }
puts absolute.join('/')

رمز بيثون:

paths = ['//depot/foo/../bar/single.c',
         '//depot/foo/docs/../../other/double.c',
         '//depot/foo/usr/bin/../../../else/more/triple.c']

def convert_path(path):
    result = []
    for item in path.split('/'):
        if item == '..':
            result.pop()
        else:
            result.append(item)
    return '/'.join(result)

for path in paths:
    print convert_path(path)

مطبوعات:

//depot/bar/single.c
//depot/other/double.c
//depot/else/more/triple.c

يمكنك استخدام نفس الخوارزمية في روبي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top