在我的Groovy程序中,我有一个行列表,并希望从列表中选择一个连续的行块。所需块的第一行包含一个特定的字符串,最后一行(我可以包含或不包含 - 无关紧要)包含一个(不同的)标记字符串。
工作代码在下面,但肯定有一种“更加通常”的方法可以在一两行中做到这一点 - 任何人都可以提出建议吗?
(实际上我的行列表来自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 :(得分:0)
正则表达式是针对此类问题而设计的。这是一个示例,显示它适用于文件内容
的位置(注意:String.find方法在groovy 1.6.1及更高版本中,在此之前你需要稍微修改一下语法)
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)
答案 1 :(得分: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)
答案 2 :(得分:0)
一个较短但有点不那么富有表现力的特德版“回复”的答案:
def extract_block(start, end, lines) {
def inBlock = false
return lines.findAll { inBlock = (it.contains(start) || inBlock) && !it.contains(end) }
}