Ruby에는 Perl이나 Python과 같은 페이지에서 텍스트를 처리할 수 있는 강력한 기능이 있다. 이 기사에서는 Ruby의 텍스트 데이터 처리 기능과 Ruby를 사용하여 CSV 데이터나 XML 데이터와 같은 형식의 텍스트 데이터를 효과적으로 처리하는 방법에 대해 간단하게 살펴본다.
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(줄 바꾸기) 문자를 포함하여 >>EOF와 EOF 사이에 있는 모든 것은 문자열의 일부로 간주된다.
Ruby 문자열 클래스에는 문자열에 저장된 데이터를 조작하고 처리하기 위한 강력한 메소드 세트가 있다. Listing 3, 4 및 5에는 이러한 메소드가 일부 표시되어 있다.
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 파일은 표로된 데이터를 표현하는 일반적인 방법이며 연락처 세부사항이 있는 연락처 목록과 같은 스프레드시트에서 데이터를 내보낼 때 자주 사용하는 형식이다.
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 파일과 데이터를 다룰 수 있는 강력한 모듈이 있다.
Ruby에는 XML 파일을 처리할 수 있는 REXML이라고 하는 강력한 내장 라이브러리가 있다. 이 라이브러리를 사용하여 XML 문서를 읽고 구문 분석할 수 있다.
이러한 XML 파일을 살펴보고 Ruby와 REXML을 사용하여 구문 분석을 해보자.
아래의 간단한 XML 파일에는 온라인 쇼핑몰에서 일반적으로 사용하는 쇼핑 카트의 내용이 표시되어 있다. 이 파일은 다음과 같은 요소로 구성되어 있다.
cart– root 요소user- 쇼핑 중인 사용자item- 사용자가 카드에 추가한 품목id, price및quantity- 품목의 하부 요소
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)에서 지정된 이름이 item인 root 요소의 모든 하부 요소를 통해 실행된다. 또한 각 요소 오브젝트에는
이러한 요소의 텍스트 값을 유지하는 text 속성이 있다.
다음에는 item 요소의 code 속성과 price와 qty 요소의 텍스트 값을 가져와서 품목의 총계를 계산한다. 청구서에 세부사항을
표시한다. 또한 품목 총계를 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에서는 cart와 item 요소 그리고 그 하부 요소를 사용하여 XML 구조를 작성한다. 이러한 요소에 값을 채운 후 Document 루트에 이 요소를 추가한다.
마찬가지로 Elements 오브젝트의 delete_element와 delete_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 article | sample-code.zip | 2KB | HTTP |
교육
- Ruby on Rails and XML: Generate a Rails stub to manipulate an XML document(Daniel Wintschel, developerWorks, 2007년 4월): 이 기사에서 Ruby on Rails를 이용하여 XML을 다루는 방법을 알 수 있다.
- Use JRuby on Rails and XML to supercharge Ajax with a Java Application Server(Tyler Anderson, developerWorks, 2008년 5월): 이 기사에서 JRuby on Rails와 Ajax 개발의 효율성을 개선할 수 있는 방법을 학습할 수 있다.
- IBM XML 인증: XML 및 관련 기술에 대한 IBM 인증 개발자가 되는 방법을 찾아볼 수 있다.
- XML Technical library: developerWorks XML 영역에서 다양한 기술 관련 기사와 팁, 튜토리얼, 표준 및 IBM Redbook을 볼 수 있다.
- 기술 서점: 다양한 기술 주제와 관련된 서적을 살펴볼 수 있다.
- developerWorks 기술 행사 및 웹 캐스트: 이들 세션에 참가하여 최신 기술에 대한 정보를 얻을 수 있다.
- developerWorks
팟캐스트: 소프트웨어 개발자의 흥미로운 인터뷰와 토론을 확인할 수 있다.
제품 및 기술 얻기
- IBM 시험판 제품을
다운로드하거나 IBM SOA Sandbox의 온라인 시험판을 살펴보고
DB2®, Lotus®, Rational®, Tivoli® 및 WebSphere®의 애플리케이션 개발 도구 및
미들웨어 제품을 사용해 볼 수 있다.
토론
- XML 영역 토론 포럼: 여러 XML 관련 토론에 참여해 볼 수 있다.
- developerWorks XML zone: Share your thoughts: 이 기사를 읽은 후 이 포럼을 통해 의견을 교환하자. XML 영역의 편집자가 의장을 맡고 있으며 언제든지 의견을 제시할 수 있다.
- developerWorks 포럼 & 블로그를 통해 developerWorks 커뮤니티에 참여하자.
