2009-12-21 7 views
37

मेरे पास फ़ाइल नाम के रूप में उपयोगकर्ता प्रविष्टियां हैं। बेशक यह एक अच्छा विचार नहीं है, इसलिए मैं [a-z], [A-Z], [0-9], _ और - को छोड़कर सब कुछ छोड़ना चाहता हूं।एक फाइल सिस्टम के लिए रूबी स्ट्रिंग को सुरक्षित कैसे करें?

उदाहरण के लिए

:

my§document$is°° very&interesting___thisIs%nice445.doc.pdf 

हो जाना चाहिए

my_document_is_____very_interesting___thisIs_nice445_doc.pdf 

और फिर आदर्श

my_document_is_very_interesting_thisIs_nice445_doc.pdf 

वहाँ ऐसा करने के लिए एक अच्छा और सुरुचिपूर्ण रास्ता नहीं है?

+1

यह एक अच्छा सवाल है। मेरी इच्छा है कि यह एक stdlib जवाब –

उत्तर

24

http://devblog.muziboo.com/2008/06/17/attachment-fu-sanitize-filename-regex-and-unicode-gotcha/ से:

def sanitize_filename(filename) 
    returning filename.strip do |name| 
    # NOTE: File.basename doesn't work right with Windows paths on Unix 
    # get only the filename, not the whole path 
    name.gsub!(/^.*(\\|\/)/, '') 

    # Strip out the non-ascii character 
    name.gsub!(/[^0-9A-Za-z.\-]/, '_') 
    end 
end 
+0

लिंक के लिए धन्यवाद! बीटीडब्ल्यू, आपके द्वारा लिंक किए गए आलेख में, पोस्टर कहता है कि इस फ़ंक्शन में समस्या है। – marcgg

+1

thx, सही .. – miku

+3

'name.gsub! (/ [^ 0-9 ए-ज़ा-जेड। \ -] /, '_') 'एकमात्र हिस्सा है जिसका मैंने 5 वर्षों के बाद उपयोग किया है: डी – Aleks

53

मैं एक समाधान है कि पुराने एक से अलग है सुझाव देना चाहते हैं। ध्यान दें कि पुराना व्यक्ति returning को बहिष्कृत करता है। वैसे, यह रेल के लिए विशिष्ट है, और आपने स्पष्ट रूप से अपने प्रश्न में रेल का उल्लेख नहीं किया है (केवल एक टैग के रूप में)। साथ ही, मौजूदा समाधान .doc.pdf को _doc.pdf में एन्कोड करने में विफल रहता है, जैसा आपने अनुरोध किया था। और, ज़ाहिर है, यह अंडरस्कोर को एक में पतन नहीं करता है।

def sanitize_filename(filename) 
    # Split the name when finding a period which is preceded by some 
    # character, and is followed by some character other than a period, 
    # if there is no following period that is followed by something 
    # other than a period (yeah, confusing, I know) 
    fn = filename.split /(?<=.)\.(?=[^.])(?!.*\.[^.])/m 

    # We now have one or two parts (depending on whether we could find 
    # a suitable period). For each of these parts, replace any unwanted 
    # sequence of characters with an underscore 
    fn.map! { |s| s.gsub /[^a-z0-9\-]+/i, '_' } 

    # Finally, join the parts with a period and return the result 
    return fn.join '.' 
end 

आप रूपांतरण के बारे में सभी विवरण निर्दिष्ट नहीं किया है:

यहाँ मेरी समाधान है। इस प्रकार, मैं निम्नलिखित मान्यताओं बना रही हूँ:

  • होनी चाहिए सबसे एक फ़ाइल नाम एक्सटेंशन, जिसका अर्थ है कि वहाँ फ़ाइल नाम
  • अवधि से पीछे चल में सबसे अधिक एक अवधि पर होना चाहिए एक के शुरू होने से चिह्नित नहीं करते पर विस्तार
  • अग्रणी अवधि एक विस्तार
  • A परे पात्रों का कोई भी क्रम की शुरुआत का प्रतीक नहीं है - Z, a - z, 0 - 9 और - एक भीमें ढह जाना चाहिए(यानी। रेखांकित अपने आप में एक को अनुमति नहीं दी चरित्र के रूप में माना जाता है, और स्ट्रिंग '$%__°#''_' बन जाएगा - '___' भागों '$%', '__' और '°#') से बजाय

इस के जटिल हिस्सा है जहाँ मैं मुख्य भाग में फ़ाइल नाम विभाजित और विस्तार। एक नियमित अभिव्यक्ति की मदद से, मैं आखिरी अवधि की खोज कर रहा हूं, जिसके बाद अवधि के अलावा कुछ और है, ताकि स्ट्रिंग में समान मानदंडों से मेल खाने वाली कोई भी अवधि न हो। हालांकि, यह सुनिश्चित करने के लिए कुछ वर्णों से पहले होना चाहिए कि यह स्ट्रिंग में पहला अक्षर नहीं है।

समारोह परीक्षण से मेरे परिणाम:

1.9.3p125 :006 > sanitize_filename 'my§document$is°° very&interesting___thisIs%nice445.doc.pdf' 
=> "my_document_is_very_interesting_thisIs_nice445_doc.pdf" 

जो मुझे लगता है कि तुम क्या अनुरोध किया है। मुझे आशा है कि यह काफी अच्छा और सुरुचिपूर्ण है।

+0

धन्यवाद! इससे मदद मिली :) – Surya

+0

जब मैं कोड का उपयोग करने का प्रयास करता हूं तो "अपरिभाषित (? ... अनुक्रम ..." प्राप्त करना। रूबी संस्करण के साथ कोई सीमाएं? –

+0

@ जेपी। बेहद देर से जवाब के लिए खेद है, और शायद आपने इसे अब तक अपने आप से बाहर निकाला है। इसका परीक्षण नहीं किया है, लेकिन मेरा मानना ​​है कि देखो-पीछे (जो प्रश्न चिह्न इंगित करता है) रुबी 1.9 में दिखाई दिया। तो हाँ, सीमाएं हैं। उदाहरण के लिए देखें http://stackoverflow.com/q/7605615/1117365 –

15

यदि आप रेल का उपयोग करते हैं तो आप स्ट्रिंग # पैरामीटर का भी उपयोग कर सकते हैं। यह विशेष रूप से इसके लिए नहीं है, लेकिन आप एक संतोषजनक परिणाम प्राप्त करेंगे।

"my§document$is°° very&interesting___thisIs%nice445.doc.pdf".parameterize 
+1

यह isn ' तकनीकी रूप से सटीक नहीं है क्योंकि यह दशमलव वर्ण को भी हटा देगा, जो एक्सटेंशन को संरक्षित करने में कुछ हद तक आवश्यक है। सौभाग्य से, पैरामीटर के पीछे कोड [अपेक्षाकृत सरल] है (http://apidock.com/rails/ActiveSupport/Inflector/parameterize) और इसे केवल कुछ 'gsub' कॉल के साथ कार्यान्वित किया जा सकता है। –

0

रेल के लिए मुझे लगने किसी भी फाइल एक्सटेंशन रखना चाहते थे लेकिन पात्रों के शेष के लिए parameterize का उपयोग कर:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/inflector/transliterate.rb

def parameterize(string, separator: "-", preserve_case: false) 
    # Turn unwanted chars into the separator. 
    parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator) 
    #... some more stuff 
end 
:

filename = "my§doc$is°° very&itng___thsIs%nie445.doc.pdf" 
cleaned = filename.split(".").map(&:parameterize).join(".") 

क्रियान्वयन विवरण और विचारों का स्रोत देखने

0

एक पुस्तकालय है जो सहायक हो सकती है, खासकर यदि आप अजीब अन को बदलने में रुचि रखते हैं ASCII के साथ icode अक्षर: unidecode

irb(main):001:0> require 'unidecoder' 
=> true 
irb(main):004:0> "Grzegżółka".to_ascii 
=> "Grzegzolka" 
संबंधित मुद्दे