Ruby에서 파일의 행을 읽는 방법


238

다음 코드를 사용하여 파일에서 줄을 읽으려고했습니다. 그러나 파일을 읽을 때 내용은 모두 한 줄에 있습니다.

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

그러나이 파일 은 각 줄을 개별적으로 인쇄합니다.


stdin을 사용해야합니다 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.
Tin Man

사용하여 line.chomp라인 엔딩을 처리하기 위해 (의 호의 @SreenivasanAC )
Yarin

답변:


150

내 대답은 모두 이후에 행 끝의 모든 종류의 처리에 대한 새로운 우려 커버 생각 "\r\n""\r"리눅스 표준으로 변환 "\n"선을 구문 분석하기 전에합니다.

"\r"일반 "\n""\r\n"Windows에서 EOL 문자 를 지원하려면 다음 과 같이 하십시오.

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, Windows \ r \ n, mac은 \ n을 사용합니다. .gsub (/ (\ r | \ n) + /, "\ n")은 모든 경우에 저에게 효과적이었습니다.
포드

4
/\r?\n/포드의 의견처럼 빈 줄을 결합하지 않고 \ r \ n과 \ n을 모두 포함하는 올바른 정규식이 있어야합니다.
Irongaze.com

12
전체 파일을 메모리로 읽어 들일 수 있으며 파일의 크기에 따라 불가능할 수 있습니다.
eremzeit

1
이 방법은 매우 비효율적이며 여기서 talabes 는 stackoverflow.com/a/17415655/228589 가 가장 적합합니다. 이 두 가지 방법의 구현을 확인하십시오.
CantGetANick

1
이것은 루비가 아닙니다. 아래의 답변은 올바른 행동을 보여줍니다.
Merovex

525

루비에는 이것을위한 방법이 있습니다 :

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

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


이 방법은 @Olivier L 인 방법보다 느리다
HelloWorld

1
@HelloWorld 메모리에서 각 선행 행을 삭제하고 각 행을 메모리로로드하기 때문일 수 있습니다. 틀렸을 수도 있지만, 루비는 아마도 제대로하고 있습니다 (큰 파일은 스크립트 충돌을 일으키지 않습니다).
Starkers

with_index이것도 사용할 수 있습니까 ?
Joshua Pinter

1
예, 예를 들면 다음과 같습니다.File.readlines(filename).each_with_index { |line, i| puts "#{i}: #{line}" }
wulftone

이 방법이 더 좋아 보입니다. 매우 큰 파일을 읽는 중이므로 전체 파일을 한 번에 메모리에로드하려고 시도해도 응용 프로그램이 중단되지 않습니다.
Shelby S

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

이것은 전체 파일을 메모리에 넣지 않고 파일의 각 줄에 대해 주어진 블록을 실행합니다. IO :: foreach를 참조하십시오 .


10
이것은 관용적 인 루비이며 파일을 문지르지 않습니다. 참조 stackoverflow.com/a/5546681/165673
Yarin

4
모두 루비 신들을 환영합니다!
Joshua Pinter

루프 내부의 두 번째 줄로 이동하는 방법?
user1735921

18

첫 번째 파일에는 Mac Classic 줄 끝이 있습니다 ( "\r"일반적인 대신 "\n"). 로 열어

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

줄 끝을 지정합니다.


1
안타깝게도 파이썬에는 보편적 인 줄 바꿈과 같은 것이 없습니다.
Josh Lee

질문 하나 더, 나는 루비 my_prog.rb <file.txt와 같은 stdin을 사용해야합니다.
그리기

전체 파일을 메모리에로드해도 괜찮다면 Olivier의 답변이 도움이 될 것 같습니다. 파일을 스캔하는 동안 줄 바꿈을 감지하면 약간의 작업이 필요합니다.
Josh Lee

7

각 줄의 끝 때문입니다. 루비에서 chomp 메소드를 사용하여 끝에서 '\ n'또는 'r'을 삭제하십시오.

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

2
chomp에 대한 @SreenivisanAC +1!
Yarin

7

헤더가있는 파일에 대한 다음 접근법의 일부입니다.

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

이를 통해 컨텐츠 행과 다르게 헤더 행을 처리 할 수 ​​있습니다.



4

런타임 중에 RAM을 늪에 빠뜨릴 수있는 큰 줄이있는 파일을 읽는 데 관심이있는 경우 항상 파일 조각을 읽을 수 있습니다. " 파일 슬러 핑이 나쁜 이유 "를 참조하십시오 .

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.