2010-11-24 7 views

उत्तर

11

ठीक है, अगर तुम eval समाधान पसंद नहीं है, मैं एक साधारण राज्य मशीन रूबी में सरल "\ t" तार में सही ढंग से पार्स करने के लिए "\ n" और काट दिया है उसके सहित पूर्व ई, बैकस्लैश खुद को स्कैपिंग। संदेश यह है:

BACKSLASH = "\\" 

def unescape_c_string(s) 
    state = 0 
    res = '' 
    s.each_char { |c| 
     case state 
     when 0 
      case c 
      when BACKSLASH then state = 1 
      else res << c 
      end 
     when 1 
      case c 
      when 'n' then res << "\n"; state = 0 
      when 't' then res << "\t"; state = 0 
      when BACKSLASH then res << BACKSLASH; state = 0 
      else res << BACKSLASH; res << c; state = 0 
      end 
     end 
    } 
    return res 
end 

यह एक आसानी से \123 की तरह, बहु चरित्र संस्थाओं सहित अधिक वर्ण, समर्थन करने के लिए बढ़ाया जा सकता है। टेस्ट इकाई साबित होता है कि यह काम करता है:

require 'test/unit' 

class TestEscapeCString < Test::Unit::TestCase 
    def test_1 
     assert_equal("abc\nasd", unescape_c_string('abc\nasd')) 
    end 
    def test_2 
     assert_equal("abc\tasd", unescape_c_string('abc\tasd')) 
    end 
    def test_3 
     assert_equal("abc\\asd", unescape_c_string('abc' + BACKSLASH * 2 + 'asd')) 
    end 
    def test_4 
     assert_equal("abc\\nasd", unescape_c_string('abc' + BACKSLASH * 2 + 'nasd')) 
    end 
    def test_5 
     assert_equal("abc\\\nasd", unescape_c_string('abc' + BACKSLASH * 3 + 'nasd')) 
    end 
    def test_6 
     assert_equal("abc\\\\nasd", unescape_c_string('abc' + BACKSLASH * 4 + 'nasd')) 
    end 
end 
3

छोटा, और भी अधिक hacky और काफी खतरनाक है, eval की वजह से:

eval "\"#{string}\""
एक साधारण उदाहरण:
 
> a = '1\t2\n3' 
> puts a 
1\t2\n3 
> puts eval "\"#{a}\"" 
1  2 
3 

+0

हाँ, कि मेरे पास हुआ था ... लेकिन eval बुराई :-) – Simon

0

संपादित करें: ध्यान दें कि यह वास्तव में काम नहीं करता। आपको वास्तव में एक राज्य मशीन के साथ एक उचित पार्सर बनाने की आवश्यकता है जो ट्रैक करता है कि आप बचने के अनुक्रम में हैं या नहीं।


रूबी ही भागने दृश्यों के कई का समर्थन करता है, तो आप इस तरह एक सरल अनुवाद तालिका बना सकते हैं:

T = { 
    '\n' => "\n", 
    '\t' => "\t", 
    '\r' => "\r" 
} 

और फिर उपयोग करें कि अनुवाद तालिका स्रोत स्ट्रिंग में उन दृश्यों को बदलने के लिए:

a = '1\t2\n3' 

a.gsub(/#{T.keys.map(&Regexp.method(:escape)).join('|')}/, &T.method(:[])) 
# => "1\t2\n3" 
+4

यह या तो काम नहीं करेगा है; पार्सिंग "\ n" संरचनाएं थोड़ा कठिन है कि केवल एक खोज-और-प्रतिस्थापन - आपको पहले भागने के दृश्यों से बचने के लिए देखना होगा। वास्तव में, बस एक लाइन, बाइट-बाय-बाइट जाकर करना बहुत आसान है। – GreyCat

+0

मुझे पसंद है कि आप वहां 'टी' के साथ क्या कर रहे हैं, यद्यपि! – Ashe

संबंधित मुद्दे

 संबंधित मुद्दे