रूबी में किसी फ़ाइल की पंक्तियों को कैसे पढ़ें


238

मैं एक फ़ाइल से लाइनों को पढ़ने के लिए निम्न कोड का उपयोग करने की कोशिश कर रहा था। लेकिन फ़ाइल पढ़ते समय , सामग्री सभी एक पंक्ति में होती है:

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line}"
end

लेकिन यह फ़ाइल प्रत्येक पंक्ति को अलग से प्रिंट करती है।


मुझे स्टडिन का उपयोग करना है, जैसे ruby my_prog.rb < file.txt, जहां मैं यह नहीं मान सकता कि लाइन-एंडिंग चरित्र वह क्या है जो फ़ाइल का उपयोग करता है। मैं इसे कैसे संभाल सकता हूं?


7
करने के बजाय line_num = 0, आप उपयोग each.each_with_indexया संभवतः कर सकते हैं each.with_index
एंड्रयू ग्रिम

@ andrew-grimm धन्यवाद, यह क्लीनर कोड बनाता है।
आकर्षित

क्यों लाइन-बाय-लाइन IO का उपयोग करने के लिए पसंद किया जाता है, इसके लिए stackoverflow.com/q/25189262/128421 देखें read
टीन मैन

का प्रयोग करें line.chomp(के सौजन्य से लाइन अंत संभाल करने @SreenivasanAC )
Yarin

जवाबों:


150

मेरा मानना ​​है कि मेरा उत्तर दोनों के बाद से किसी भी प्रकार के लाइन एंडिंग से निपटने के बारे में आपकी नई चिंताओं को कवर करता है "\r\n"और लाइनों को पार्स करने से पहले "\r"लिनक्स मानक में बदल जाता है "\n"

"\r"नियमित रूप से "\n"और "\r\n"विंडोज से ईओएल चरित्र का समर्थन करने के लिए , यहां मैं क्या करूंगा:

line_num=0
text=File.open('xxx.txt').read
text.gsub!(/\r\n?/, "\n")
text.each_line do |line|
  print "#{line_num += 1} #{line}"
end

बेशक यह बहुत बड़ी फ़ाइलों पर एक बुरा विचार हो सकता है क्योंकि इसका मतलब है कि पूरी फ़ाइल को मेमोरी में लोड करना।


उस रेग्ज ने मेरे लिए काम नहीं किया। यूनिक्स प्रारूप \ n, विंडोज़ \ r \ n का उपयोग करता है, मैक \ n का उपयोग करता है - (/ (\ r_ \ n) + /, "\ n") मेरे लिए सभी मामलों के साथ काम करता है।
पॉड

4
सही रेगेक्स ऐसा होना चाहिए /\r?\n/जो पॉड की टिप्पणी के बिना खाली लाइनों के संयोजन के बिना दोनों \ r \ n और \ n को कवर करेगा
Irongaze.com

12
यह पूरी फ़ाइल को मेमोरी में पढ़ेगा, जो कि फ़ाइल कितनी बड़ी है, इस पर निर्भर करना असंभव हो सकता है।
इरेन्जिट

1
यह विधि बहुत ही अकुशल है, यहाँ पर तालबेहट उत्तर देते हैं stackoverflow.com/a/17415655/228589 सबसे अच्छा उत्तर है। कृपया इन दो विधियों के कार्यान्वयन की पुष्टि करें।
कैंटजनेटिक

1
यह माणिक तरीका नहीं है। नीचे दिया गया उत्तर सही व्यवहार दिखाता है।
मेरोवेक्स

525

रूबी के पास इसके लिए एक तरीका है:

File.readlines('foo').each do |line|

http://ruby-doc.org/core-1.9.3/IO.html#method-c-readlines


मेथोंड की तुलना में यह मेथॉन्ड धीमा है जो @Olivier L.
HelloWorld

1
@ हेलोवर्ल्ड शायद इसलिए क्योंकि यह प्रत्येक पूर्ववर्ती रेखा को मेमोरी से हटा रहा है और प्रत्येक लाइन को मेमोरी में लोड कर रहा है। गलत हो सकता है, लेकिन रूबी शायद ठीक से काम कर रही है (ताकि बड़ी फाइलें आपकी स्क्रिप्ट को क्रैश न करें)।
स्टार्कर

आप with_indexइस के साथ भी उपयोग कर सकते हैं ?
जोशुआ पिन्टर

1
हां, आप कर सकते हैं, उदाहरण के लिएFile.readlines(filename).each_with_index { |line, i| puts "#{i}: #{line}" }
wulftone

यह तरीका बेहतर लगता है। मैं बहुत बड़ी फाइलें पढ़ रहा हूं और इस तरह यह पूरी फाइल को एक ही बार में मेमोरी में लोड करने का प्रयास करके क्रैश नहीं करता है।
शेल्बी एस

393
File.foreach(filename).with_index do |line, line_num|
   puts "#{line_num}: #{line}"
end

यह फ़ाइल में प्रत्येक पंक्ति के लिए दिए गए ब्लॉक को पूरी फ़ाइल को मेमोरी में स्लैप किए बिना निष्पादित करेगा। देखें: आईओ :: foreach


10
यह जवाब है - मुहावरेदार रूबी और फ़ाइल को नहीं खुरचती है। यह भी देखें stackoverflow.com/a/5546681/165673
यारिन

4
सभी रूबी देवताओं की जय हो!
जोशुआ पिन्टर

लूप के अंदर दूसरी पंक्ति में कैसे जाएं?
user1735921

18

आपकी पहली फ़ाइल में मैक क्लासिक लाइन एंडिंग्स हैं (यह "\r"सामान्य के बजाय "\n") है। इसके साथ खोलें

File.open('foo').each(sep="\r") do |line|

लाइन अंत निर्दिष्ट करने के लिए।


1
अफसोस की बात है कि पायथन में यूनिवर्सल न्यूलाइन्स जैसा कुछ नहीं है, कम से कम मुझे पता है।
जोश ली

एक और सवाल, मैं रूबी my_prog.rb <file.txt की तरह स्टड का उपयोग करना है, जहां मैं यह नहीं मान सकता कि फ़ाइल का उपयोग करने वाली चार्ट को समाप्त करने वाली लाइन क्या उपयोग करती है ... मैं इसे कैसे संभाल सकता हूं?
ड्रा

ओलिवियर का उत्तर सहायक लगता है, यदि आप पूरी फ़ाइल को मेमोरी में लोड करने के साथ ठीक हैं। फ़ाइल को स्कैन करते समय नई सुर्खियों का पता लगाना थोड़ा और काम करेगा।
जोश ली

7

यह प्रत्येक लाइनों में endlines के कारण है। अंत में '\ n' या 'r' को हटाने के लिए रूबी में chomp विधि का उपयोग करें।

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line.chomp}"
end

2
धूमधाम के लिए @SreenivisanAC +1!
यारिन

7

मैं उन फ़ाइलों के लिए निम्नलिखित दृष्टिकोण के लिए आंशिक हूं जिनमें हेडर हैं:

File.open(file, "r") do |fh|
    header = fh.readline
    # Process the header
    while(line = fh.gets) != nil
        #do stuff
    end
end

यह आपको हेडर लाइन (या लाइनों) को सामग्री लाइनों से अलग संसाधित करने की अनुमति देता है।



4

यह मत भूलो कि यदि आप किसी ऐसी फ़ाइल में पढ़ने के बारे में चिंतित हैं, जिसमें बड़ी लाइनें हो सकती हैं जो रनिंग के दौरान आपकी रैम को स्वाइप कर सकती हैं, तो आप हमेशा फ़ाइल का टुकड़ा-भोजन पढ़ सकते हैं। " एक फ़ाइल खराब क्यों है " देखें ।

File.open('file_path', 'rb') do |io|
  while chunk = io.read(16 * 1024) do
    something_with_the chunk
    # like stream it across a network
    # or write it to another file:
    # other_io.write chunk
  end
end
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.