IBM®
메인 컨텐츠로 가기
    Korea [국가변경]    이용약관
 
 
   
        제품    서비스 & 솔루션    고객지원 & 다운로드    회원 서비스    
메인 컨텐츠로 가기

한국 developerWorks  >  XML  >

Ruby를 사용한 텍스트 처리

Ruby의 강력한 기능을 이용하여 텍스트를 효과적으로 처리하기

developerWorks
문서 옵션
PDF format - Fits A4 and Letter

PDF - Fits A4 and Letter
45KB (15 pages)

Get Adobe® Reader®

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

샘플 코드

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Santhosh Krishnamoorthy, Staff Software Engineer, IBM

원문 게재일 : 2009 년 8 월 18 일
번역 게재일 : 2009 년 11 월 03 일

Ruby는 무료이며 단순하고 확장과 이식이 가능하며 기능이 다양한 오브젝트 지향 스크립팅 언어입니다. 강력한 텍스트 처리 언어인 Ruby는 가능성이 무한합니다. 강력한 내장 라이브러리와 외부 라이브러리 세트를 갖고 있는 Ruby는 일상적으로 마주치게 되는 모든 텍스트 처리 작업을 해결할 수 있는 실용적인 방안이 될 수 있습니다.

Ruby에는 Perl이나 Python과 같은 페이지에서 텍스트를 처리할 수 있는 강력한 기능이 있다. 이 기사에서는 Ruby의 텍스트 데이터 처리 기능과 Ruby를 사용하여 CSV 데이터나 XML 데이터와 같은 형식의 텍스트 데이터를 효과적으로 처리하는 방법에 대해 간단하게 살펴본다.

Ruby 문자열

자주 사용하는 약어
  • CSV: Comma Separated Values
  • REXML: Ruby Electric XML
  • XML: Extensible Markup Language

Ruby의 문자열은 텍스트 데이터를 유지, 비교, 조작할 수 있는 강력한 도구이다. Ruby의 문자열은 하나의 클래스로 String::new를 호출하거나 단지 리터럴 값을 할당하여 인스턴스화할 수 있다.

문자열에 값을 할당할 경우에는 한 쌍의 작은따옴표(')나 큰따옴표를 사용하여 해당 값을 둘러싼다. 작은따옴표와 큰따옴표를 사용하여 문자열을 지정하는 방식은 몇 가지가 있다. 큰따옴표를 사용하면 첫 머리에 백슬래시를 사용하는 Escape 시퀀스가 가능하며 또한 #{} 연산자를 사용하여 문자열 안에 있는 표현식을 평가할 수 있다. 문자열을 작은따옴표로 둘러싸면 순수한 리터럴이된다.

Listing 1에는 관련 예제가 표시되어 있다.


Listing 1. Ruby에서 문자열 정의하기


message = 'Heal the World…'

puts message

message1 = "Take home Rs #{100*3/2} "

puts message1

Output :

# ./string1.rb

# Heal the World…

# Take home Rs 150


여기서 첫 번째 문자열은 한 쌍의 작은따옴표를 사용하여 정의하였다. 두 번째는 한 쌍의 큰따옴표를 사용하였다. 두 번째 예에서는 #{} 안에 있는 표현식을 먼저 평가한 후에 값을 표시한다.

문자열을 정의하는 또 다른 유용한 방식으로는 다중 라인 문자열 정의를 사용하는 방법이 있다.

여기부터는 대화식 Ruby 콘솔인 irb>>를 사용하여 설명한다. Ruby 설치판을 사용하여 이 콘솔을 설치해야 한다. 설치하지 않은 경우 irb Ruby gem을 가져와서 설치한다. 이는 Ruby와 그 모듈을 학습하는 데 필요한 매우 유용한 도구이다. 설치한 경우 irb>> 명령을 사용하여 실행할 수 있다.


Listing 2. Ruby에서 다중 라인 문자열 정의하기


irb>> str = >>EOF

irb>> "hello world

irb>> "how do you feel?

irb>> "how r u ?

irb>> EOF

"hello, world\nhow do you feel?\nhow r u?\n"

irb>> puts str

hello, world
how do you feel?
how r u?


Listing 2에서 \n(줄 바꾸기) 문자를 포함하여 >>EOFEOF 사이에 있는 모든 것은 문자열의 일부로 간주된다.

Ruby 문자열 클래스에는 문자열에 저장된 데이터를 조작하고 처리하기 위한 강력한 메소드 세트가 있다. Listing 3, 45에는 이러한 메소드가 일부 표시되어 있다.


Listing 3. Ruby에서 문자열 병합하기


irb>> str = "The world for a horse"    # String initialized with a value

The world for a horse

irb>> str*2                     # Multiplying with an integer returns a 
                                         # new string containing that many times
                                         # of the old string.

The world for a horseThe world for a horse

irb>> str + " Who said it ? "      # Concatenation of strings using the '+' operator

The world for a horse Who said it ?

irb>> str<<" is it? "	  # Concatenation using the '<<' operator

The world for a horse is it?


하위 문자열을 추출하고 이 문자열의 일부를 조작하기


Listing 4. Ruby에서 문자열을 추출하고 조작하기


irb>> str[0]	# The '[]' operator can be used to extract substrings, just 
                        # like accessing entries in an array.
                        # The index starts from 0.
84			# A single index returns the ascii value
                        # of the character at that position

irb>> str[0,5]	# a range can be specified as a pair. The first is the starting 
                        # index , second is the length of the substring from the
                        # starting index.

The w

irb>> str[16,5]="Ferrari"   # The same '[]' operator can be used
                                  # to replace substrings in a string
                                  # by using the assignment like '[]='
irb>>str

The world for a Ferrari

Irb>> str[10..22]		# The range can also be specified using [x1..x2] 

for a Ferrari

irb>> str[" Ferrari"]=" horse"	# A substring can be specified to be replaced by a new
                               # string. Ruby strings are intelligent enough to adjust the
                               # size of the string to make up for the replacement string.

irb>> s

The world for a horse

irb>> s.split	       # Split, splits the string based on the given delimiter
                               # default is a whitespace, returning an array of strings.

["The", "world", "for", "a", "horse"]

irb>> s.each(' ') { |str| p str.chomp(' ') }

                               # each , is a way of block processing the
			       # string splitting it on a record separator
			       # Here, I use chomp() to cut off the trailing space

"The"
"world"
"for"
"a"
"horse"


Ruby 문자열 클래스에서는 대소문자를 서로 변경하고, 길이를 구하고, 레코드 분리 문자를 제거하고, 문자열을 검색하고, 문자열을 암호화하거나 해독하는 메소드 등과 같은 매우 다양한 유틸리티 메소드를 사용할 수 있다. 또 다른 유용한 방법은 문자열이 변경되지 않도록 할 수 있는 freeze 메소드이다. 문자열 str(str.freeze)에서 이 메소드를 호출하면 str은 수정할 수 없다.

또한 Ruby에는 소멸자(destructor) 메소드라고 하는 것이 있다. 느낌표(!)로 끝나는 메소드는 문자열을 영구적으로 수정한다. 끝에 느낌표가 없는 일반 메소드는 메소드를 호출한 문자열의 사본을 수정하고 리턴한다. 반면에 느낌표로 끝나는 메소드는 메소드를 호출한 문자열을 수정한다.


Listing 5. Ruby 문자열 다루기: 영구적으로 문자열 수정하기


irb>> str = "hello, world"

hello, world

irb>> str.upcase

HELLO, WORLD

irb>>str		       # str, remains as is.

Hello, world

irb>> str.upcase!	       # here, str gets modified by the '!' at the end of 
                               # upcase.
HELLO, WORLD

irb>> str

HELLO, WORLD


Listing 5에서 str의 문자열은 upcase! 메소드에 의해 수정되지만 upcase 메소드는 대소문자가 변경된 문자열의 사본을 리턴한다. 이러한 느낌표(!)가 있는 메소드는 때로는 매우 유용하다.

Ruby 문자열은 매우 강력하다. 일단 문자열에서 데이터를 캡처하면 다양한 메소드를 사용하여 매우 쉽고 효과적으로 데이터를 처리할 수 있다.




위로


CSV 파일 처리하기

CSV 파일은 표로된 데이터를 표현하는 일반적인 방법이며 연락처 세부사항이 있는 연락처 목록과 같은 스프레드시트에서 데이터를 내보낼 때 자주 사용하는 형식이다.

Ruby에는 이러한 파일을 처리할 수 있는 강력한 라이브러리가 있다. csv는 CSV 파일을 처리하는 Ruby 모듈이다. 이 모듈에는 CSV 파일을 작성하고, 읽고, 구문 분석할 수 있는 메소드가 있다.

Listing 6의 예제에는 Ruby csv 모듈을 사용하여 이러한 CSV 파일을 작성하고 구문 분석하는 방법이 표시되어 있다.


Listing 6. CSV 파일 다루기: CSV 파일의 작성 및 구문 분석


require 'csv'

writer = CSV.open('mycsvfile.csv','w')

begin

	print "Enter Contact Name: "

	name = STDIN.gets.chomp

	print "Enter Contact No: "

	num = STDIN.gets.chomp

	s = name+" "+num

	row1 = s.split

	writer << row1

	print "Do you want to add more ? (y/n): "

	ans = STDIN.gets.chomp

end while ans != "n"

writer.close

file = File.new('mycsvfile.csv')

lines = file.readlines

parsed = CSV.parse(lines.to_s)

p parsed

puts ""

puts "Details of Contacts stored are as follows..."

puts ""

puts "-------------------------------"

puts "Contact Name | Contact No"

puts "-------------------------------"

puts ""

CSV.open('mycsvfile.csv','r') do |row|

	puts row[0] + " | " + row[1]	

	puts ""
end


Listing 7에는 출력 내용이 표시되어 있다.


Listing 7 CSV 파일 다루기: CSV 파일 출력의 작성 및 구문 분석


Enter Contact Name: Santhosh

Enter Contact No: 989898

Do you want to add more ? (y/n): y

Enter Contact Name: Sandy

Enter Contact No: 98988

Do you want to add more ? (y/n): n

Details of Contacts stored are as follows...

---------------------------------
Contact Name | Contact No
---------------------------------

Santhosh | 989898

Sandy | 98988


이제 예제를 간단히 살펴보자.

먼저, Ruby csv 모듈을 포함한다(require 'csv').

이름이 mycsvfile.csv인 CSV 파일을 작성하기 위해 CSV.open() 호출을 사용하여 이 파일을 연다. 이렇게 하면 기록기 오브젝트가 리턴된다.

이 예제에서는 간단한 연락처 목록이 있는 CSV 파일을 작성하고 인명과 전화번호를 저장한다. 이 예제의 루프를 통해 사용자는 연락처 이름과 전화번호를 입력하게 된다. 이름과 전화번호를 하나의 문자열로 병합한 후 다시 두 개의 문자열로 구성된 하나의 배열로 분리한다. 이 배열을 기록기 오브젝트에 전달하여 CSV 파일에 쓴다. 따라서 한 쌍의 CSV 값이 이 파일에 하나의 라인으로 저장된다.

루프가 끝나면 모든 과정이 완료된다. 이제 기록기를 닫고 파일에 있는 데이터를 저장한다.

다음 단계에서는 작성한 CSV 파일을 구문 분석한다.

이 파일을 열고 구문 분석하는 한가지 방법은 새로운 이름의 CSV 파일을 사용하는 새 File 오브젝트를 작성하는 것이다.

readlines 메소드를 호출하여 이 파일의 모든 라인을 읽어서 lines라고 하는 배열로 보낸다.

lines.to_s를 호출하여 lines 배열을 String 오브젝트로 변환하고 이 문자열을 CSV 데이터를 구문 분석하여 중복 배열로 해당 내용을 리턴하는 CSV.parse 메소드로 전달한다.

다음에는 이 파일을 열고 구문 분석하는 또 다른 방법이 표시되어 있다. 읽기 모드로 호출하는 CSV.open 메소드를 사용하여 다시 이 파일을 연다. 이렇게 하면 여러 개의 행으로 구성된 하나의 배열이 리턴된다. 일부 서식을 사용하여 각 행을 인쇄하여 연락처 세부사항을 표시한다. 여기에 있는 각 행은 CSV 파일의 한 라인에 해당한다.

아는 바와 같이 Ruby에는 CSV 파일과 데이터를 다룰 수 있는 강력한 모듈이 있다.




위로


XML 파일 다루기

Ruby에는 XML 파일을 처리할 수 있는 REXML이라고 하는 강력한 내장 라이브러리가 있다. 이 라이브러리를 사용하여 XML 문서를 읽고 구문 분석할 수 있다.

이러한 XML 파일을 살펴보고 Ruby와 REXML을 사용하여 구문 분석을 해보자.

아래의 간단한 XML 파일에는 온라인 쇼핑몰에서 일반적으로 사용하는 쇼핑 카트의 내용이 표시되어 있다. 이 파일은 다음과 같은 요소로 구성되어 있다.

  • cart – root 요소
  • user - 쇼핑 중인 사용자
  • item - 사용자가 카드에 추가한 품목
  • id, pricequantity - 품목의 하부 요소

Listing 8에는 XML의 구조가 표시되어 있다.


Listing 8. XML 파일 다루기: 샘플 XML 파일


<cart id="userid">

<item code="item-id">

	<price>

		<price/unit>

	</price>

	<qty>

		<number-of-units>

	</qty>

</item>

</cart>


다운로드로 이동하여 샘플 XML 파일을 다운로드한다. 이제 REXML을 사용하는 트리를 통해 이 XML 파일을 로드하고 구문 분석하자.


Listing 9. XML 파일 다루기: XML 파일의 구문 분석


require 'rexml/document'

include REXML

file = File.new('shoppingcart.xml')

doc = Document.new(file)

root = doc.root

puts ""

puts "Hello, #{root.attributes['id']}, Find below the bill generated for your purchase..."

puts ""

sumtotal = 0

puts "-----------------------------------------------------------------------"

puts "Item\t\tQuantity\t\tPrice/unit\t\tTotal"

puts "-----------------------------------------------------------------------"

root.each_element('//item') { |item| 

code = item.attributes['code']

qty = item.elements["qty"].text.split(' ')

price = item.elements["price"].text.split(' ')

total = item.elements["price"].text.to_i * item.elements["qty"].text.to_i

puts "#{code}\t\t  #{qty}\t\t          #{price}\t\t         #{total}"

puts ""

sumtotal += total

}

puts "-----------------------------------------------------------------------"

puts "\t\t\t\t\t\t     Sum total : " + sumtotal.to_s

puts "-----------------------------------------------------------------------"


Listing 10에는 출력이 표시되어 있다.


Listing 10. XML 파일 다루기: XML 파일 출력의 구문 분석


Hello, santhosh, Find below the bill generated for your purchase...

-------------------------------------------------------------------------
Item            Quantity                Price/unit              Total
-------------------------------------------------------------------------
CS001             2                          100                      200

CS002             5                          200                     1000

CS003             3                          500                     1500

CS004             5                          150                      750

-------------------------------------------------------------------------
                                                         Sum total : 3450
--------------------------------------------------------------------------


Listing 9에 있는 예제에서는 쇼핑 카트 XML 파일을 구문 분석하여 전체 개별 품목과 총 구매 금액이 표시된 청구서(Listing 10)를 생성한다.

이 예제를 간단히 살펴보자.

먼저, Ruby의 REXML 모듈을 포함한다. 이 모듈에는 XML 파일을 구문 분석을 할 수 있는 메소드가 있다.

shoppingcart.xml 파일을 열고 이 파일에서 Document 오브젝트를 작성한다. 이 Document 오브젝트에는 구문 분석한 XML 파일이 포함되어 있다.

이 문서의 루트를 요소 오브젝트 root에 할당한다. 그러면 문서의 루트가 해당 XML의 cart 태그를 가리키게 된다.

각 요소 오브젝트에는 속성 오브젝트가 있으며 이 오브젝트는 요소 속성 이름과 그 값이 각각 키와 값으로 구성된 일종의 해시이다. 여기에서는 root.attributes['id']를 통해 root 요소의 속성 id(이 경우에는 userid) 값을 제공한다.

다음에는 sumtotal을 0으로 초기화하고 헤더를 표시한다.

또한 각 요소 오브젝트에는 Elements라고 하는 오브젝트와 그 하부 요소를 액세스할 수 있는 each 및 [] 메소드가 있다. 이 블록은 XPath 표현식(//item)에서 지정된 이름이 itemroot 요소의 모든 하부 요소를 통해 실행된다. 또한 각 요소 오브젝트에는 이러한 요소의 텍스트 값을 유지하는 text 속성이 있다.

다음에는 item 요소의 code 속성과 priceqty 요소의 텍스트 값을 가져와서 품목의 총계를 계산한다. 청구서에 세부사항을 표시한다. 또한 품목 총계를 sumtotal에 추가한다.

마지막으로 품목 총계의 합계를 표시한다.

REXML와 Ruby를 사용하여 XML 파일을 구문 분석하는 것이 얼마나 쉽고 단순한지 이 예제를 통해 알 수 있다. XML 파일을 빠르게 작성하고 요소와 그 속성을 추가하고 삭제하기가 매우 쉽다.


Listing 11. XML 파일 다루기: XML 파일의 생성


doc = Document.new

doc.add_element("cart1", {"id" => "user2"})

cart = doc.root.elements[1]

item = Element.new("item")

item.add_element("price")

item.elements["price"].text = "100"

item.add_element("qty")

item.elements["qty"].text = "4"

cart .elements << item


Listing 11에서는 cartitem 요소 그리고 그 하부 요소를 사용하여 XML 구조를 작성한다. 이러한 요소에 값을 채운 후 Document 루트에 이 요소를 추가한다.

마찬가지로 Elements 오브젝트의 delete_elementdelete_attribute 메소드를 사용하여 요소와 속성을 삭제한다.

위의 예제는 트리 구문 분석(tree parsing)이라고 한다. XML 문서를 구문 분석하는 또 다른 방법은 스트림 구문 분석(stream parsing)이라고 한다. 이 방법은 트리 구문 분석보다 빠르며 속도가 중요한 부분에 사용될 수 있다. 스트림 구문 분석은 이벤트를 기반으로 하며 리스너와 함께 동작한다. 태그를 발견하면 리스너를 호출하여 구문 분석을 한다.

Listing 12에는 이에 대한 예제가 표시되어 있다.


Listing 12. XML 파일 다루기: 스트림 구문 분석


require 'rexml/document'

require 'rexml/streamlistener'

include REXML

class Listener

  include StreamListener

  def tag_start(name, attributes)

    puts "Start #{name}"

  end

  def tag_end(name)

    puts "End #{name}"

  end

end

listener = Listener.new

parser = Parsers::StreamParser.new(File.new("shoppingcart.xml"), listener)

parser.parse


Listing 13에서 출력 결과가 표시되어 있다.


Listing 13. XML 파일 다루기: 스트림 구문 분석 출력 결과


Start cart

Start item

Start price

End price

Start qty

End qty

End item

Start item

Start price

End price

Start qty

End qty

End item

Start item

Start price

End price

Start qty

End qty

End item

Start item

Start price

End price

Start qty

End qty

End item

End cart


따라서 REXML과 Ruby에는 매우 효과적이고 직관적인 방식으로 XML 데이터를 다루고 조작할 수 있는 강력한 조합 기능이 있다.




위로


요약

Ruby에는 텍스트를 빠르고, 강력하고 효과적으로 처리할 수 있는 내장 라이브러리와 외부 라이브러리가 있다. 사용자는 이러한 기능을 이용하여 직면할 수 있는 다양한 텍스트 형식의 데이터 처리 요구를 단순화하고 개선할 수 있다. 이 기사에서는 Ruby의 일부 기능만을 다루었다. 그러나 Ruby에는 보다 다양한 기능이 있다.

Ruby는 사용자에게 반드시 필요한 유용한 도구이다.





위로


다운로드 하십시오

설명이름크기다운로드 방식
Sample code for the articlesample-code.zip2KBHTTP
다운로드 방식에 대한 정보


참고자료

교육

제품 및 기술 얻기

토론


필자소개

Photo of Santhosh Krishnamoorth

Santhosh Krishnamoorthy는 인도 방갈로어에 있는 IBM Software Labs TXSeries 팀의 테스트 엔지니어로 상호 시스템 통신 및 Java 기술 분야를 담당한다. 주요 관심사는 Ruby, Ruby on Rails 및 Python 프로그래밍이다.




기사에 대한 평가


보다 나은 서비스를 제공하기 위함이오니 잠시 짬을 내어 이 양식을 제출하여 주십시오.



 


 


 


이 문서 북마킹 하기

mar.gar.in mar.gar.in naver naver eolin eolin del.icio.us del.icio.us





위로


IBM, IBM 로고, ibm.com, DB2, developerWorks, Lotus, Rational, Tivoli 및 WebSphere는 미국 또는 기타 국가에서 사용되는 International Business Machines Corporation의 상표 또는 등록 상표이다. 이와 함께 기타 IBM 상표가 기재된 용어가 상표 기호(® 또는 ™)와 함께 이 정보에 처음 표시된 경우, 이와 같은 기호는 이 정보를 발행할 때 미국에서 IBM이 소유한 등록 상표 또는 일반 법적 상표이다. 또한 이러한 상표는 기타 국가에서 등록 상표 또는 일반 법적 상표이다. 현재 IBM 상표 목록은 웹 "저작권 및 상표 정보"에 있다. Adobe, Adobe 로고, PostScript 및 PostScript 로고는 미국 또는 기타 국가에서 사용되는 Adobe Systems Incorporated의 상표 또는 등록 상표이다. Java 및 모든 Java 관련 상표는 미국 또는 기타 국가에서 사용되는 Sun Microsystems, Inc.의 상표이다. 기타 회사, 제품 및 서비스 이름은 해당 회사의 상표 또는 서비스표이다. 기타 회사, 제품, 및 서비스명은 다른 상표나 서비스 마크일 수 있습니다.

developerWorks 콘텐트를 다른 사이트에 전재하기:
developerWorks 콘텐트에 대한 저작권은 IBM에 있습니다. IBM의 서면 허가나 원본 저자의 허락이 없이는 전재를 금합니다. 저희 콘텐트를 전재하시려면 IBM developerWorks 담당자 에게 문의하십시오.
    IBM 소개 개인정보 보호정책 문의