2009-05-30 8 views
1

그루비 (Groovy) 프로그램에서 필자는 줄의 목록을 가지고 목록에서 연속적인 줄 블록을 선택하려고합니다. 원하는 블록의 첫 번째 줄에는 특정 문자열이 들어 있으며, 마지막 줄 (포함 할 수도 있고 붙이지 않을 수도 있음)은 (다른) 마커 문자열을 포함합니다.그루비 (Groovy)리스트에서 한 행의 블록을 선택하는 방법

아래 작업 코드는 있지만 한 줄 또는 두 줄에서이 작업을 수행하는 "그루브 (groov)"방법이 있습니다. 누구든지 어떻게 제안 할 수 있습니까?

는 는

(는 HTTP는 GET,하지만 난 그냥 URL 객체를 정의하고 url.openStream().의 readlines()가 선을 얻을 않는에서 실제로 라인의 내 목록입니다.)

lines = ["line1", "line2", "line3", "line4", "line5", "line6"] 
println extract_block("2", "5", lines) 

def extract_block(start, end, lines) { 
    def block = null 
    for (line in lines) { 
     if (null == block && line.contains(start)) { block = [] } 
     if (null != block && line.contains(end)) { break } 
     if (null != block) { block << line } 
    } 
    return block 
} 

이것은

를 인쇄
["line2", "line3", "line4"] 

첫 번째 줄 ("2"포함)을 포함하고 마지막 줄 ("5"포함)은 건너 뜁니다.

답변

0

테드의 "groovier"대답의 짧은하지만 다소 덜 표현 버전 :

그들이 (나를 위해 어쨌든) 읽기가 매우 어렵습니다 때문에
def extract_block(start, end, lines) { 
    def inBlock = false 
    return lines.findAll { inBlock = (it.contains(start) || inBlock) && !it.contains(end) } 
} 
0

정규 표현식은 이러한 종류의 문제를 해결하기 위해 고안되었습니다. 여기에 작동을 보여주는 예제입니다 모두 어디에 파일의 내용

:

def BEGIN_MARKER = "2" 
def END_MARKER = "5" 
def BEGIN_LINE = /.*$BEGIN_MARKER.*\n/ 
def MIDDLE_LINES = /(.*\n)*?/ 
def LOOKAHEAD_FOR_END_LINE_OR_EOF = /(?=.*$END_MARKER.*|\Z)/ 

def FIND_LINES = "(?m)" + 
       BEGIN_LINE + 
       MIDDLE_LINES + 
       LOOKAHEAD_FOR_END_LINE_OR_EOF  

def fileContents = """ 
line1 ipsum 
line2 lorem 
line3 ipsum 
line4 lorem 
line5 ipsum 
line6 lorem 
""" 

// prints: 
// line2 lorem 
// line3 ipsum 
// line4 lorem 
println fileContents.find(FIND_LINES) 

def noEndMarkerFileContents = """ 
line1 ipsum 
line2 lorem 
line3 ipsum 
line4 lorem 
line6 lorem 
""" 

// prints: 
// line2 lorem 
// line3 ipsum 
// line4 lorem 
// line6 lorem   
println noEndMarkerFileContents.find(FIND_LINES) 
(NB는 String.find 방법은 위의 그루비 1.6.1과에, 그 이전에 당신은 약간의 구문을 수정해야 할 것입니다) 정규 표현식을 사용하지 않으려면
+0

나는 멀리 정규 표현식에에서 유지하려고 노력했다. 일부 주석은 정규 표현식이 더 많은 라인을 필요로한다는 것을 이해할 수 있습니다. 그러나 나는 오히려 정말 짧고 소화 가능한 것을 사용하려고합니다. –

0

또는, 당신은 findall은 사용이 좀 더 멋 만들 수 있습니다

lines = ["line1", "line2", "line3", "line4", "line5", "line6"] 

def extract_block(start, end, lines) { 
    def inBlock = false 
    return lines.findAll { line ->   
     if (line.contains(start)) inBlock = true 
     if (line.contains(end)) inBlock = false    
     return inBlock 
    } 
} 

assert ["line2", "line3", "line4"] == extract_block("2", "5", lines) 
+0

감사합니다. 나는 이것보다 조금 더 짧게 만들었지 만, 나는 내가 한 것보다 더 많거나 적은 것이다. 누구든지 그것을 더욱 간결하게 만들 수 있다면 그것은 환영할만한 것입니다. –

관련 문제