Groovy解析文本文件

Joh*_*mos 11 groovy parsing text file

我有一个文件日志,我想解析,并有一些问题.起初它似乎很简单.我会继续发布我想出的来源,然后解释我想要做的事情.

我正在尝试解析的文件包含以下数据:

HDD Device 0 : /dev/sda
HDD Model ID  : ST3160815A
HDD Serial No : 5RA020QY
HDD Revision  : 3.AAA
HDD Size     : 152628 MB
Interface    : IDE/ATA
Temperature         : 33 C
Health  : 100%
Performance  : 70%
Power on Time : 27 days, 13 hours
Est. Lifetime : more than 1000 days

HDD Device 1 : /dev/sdb
HDD Model ID  : TOSHIBA MK1237GSX
HDD Serial No : 97LVF9MHS
HDD Revision  : DL130M
HDD Size     : 114473 MB
Interface    : S-ATA
Temperature  : 30 C
Health  : 100%
Performance  : 100%
Power on Time : 38 days, 11 hours
Est. Lifetime : more than 1000 days
Run Code Online (Sandbox Code Playgroud)

我的源代码(下面)基本上逐行拆分文件,然后将行拆分为两行(键:值).

资源:

def dataList = [:]
def theInfoName = "C:\\testdata.txt"

File theInfoFile = new File(theInfoName)

def words
def key
def value

if (!theInfoFile.exists()) {
     println "File does not exist"

} else {

 theInfoFile.eachLine { line ->

 if (line.trim().size() == 0) {
  return null

 } else {

  words = line.split("\t: ")
  key=words[0] 
  value=words[1]
  dataList[key]=value

  println "${words[0]}=${words[1]}"
  }

 }
 println "$dataList.Performance"  //test if Performance has over-written the previous Performance value
}
Run Code Online (Sandbox Code Playgroud)

我的源码的问题在于,当我使用我的getter(例如$ dataList.Performance)时,它只显示文件中的最后一个而不是两个.

所以我想知道,我如何解析文件,以便保存两个硬盘的信息?有没有办法将信息打包成'硬盘驱动器对象'?

任何和所有的帮助表示赞赏

一些附注:

该文件位于Windows机器上(即使从nix系统获取信息)

文本文件由制表符,冒号和空格分开(如我的源代码所示),我想我会说,因为它在这个页面上看起来不像.

tim*_*tes 21

这将读取块中的数据(用空行分隔块)

def dataList = []
def theInfoName = 'testdata.txt'

File theInfoFile = new File( theInfoName )

if( !theInfoFile.exists() ) {
  println "File does not exist"
} else {
  def driveInfo = [:]
  // Step through each line in the file
  theInfoFile.eachLine { line ->
    // If the line isn't blank
    if( line.trim() ) {
      // Split into a key and value
      def (key,value) = line.split( '\t: ' ).collect { it.trim() }
      // and store them in the driveInfo Map
      driveInfo."$key" = value
    }
    else {
      // If the line is blank, and we have some info
      if( driveInfo ) {
        // store it in the list
        dataList << driveInfo
        // and clear it
        driveInfo = [:]
      }
    }
  }
  // when we've finished the file, store any remaining data
  if( driveInfo ) {
    dataList << driveInfo
  }
}

dataList.eachWithIndex { it, index ->
  println "Drive $index"
  it.each { k, v ->
    println "\t$k = $v"
  }
}
Run Code Online (Sandbox Code Playgroud)

手指越过你的硬盘信息部分之间有空行(你在测试数据中显示了一个):-)

顺便说一句:我得到以下输出:

Drive 0
    HDD Device 0 = /dev/sda
    HDD Model ID = ST3160815A
    HDD Serial No = 5RA020QY
    HDD Revision = 3.AAA
    HDD Size = 152628 MB
    Interface = IDE/ATA
    Temperature = 33 C
    Health = 100%
    Performance = 70%
    Power on Time = 27 days, 13 hours
    Est. Lifetime = more than 1000 days
Drive 1
    HDD Device 1 = /dev/sdb
    HDD Model ID = TOSHIBA MK1237GSX
    HDD Serial No = 97LVF9MHS
    HDD Revision = DL130M
    HDD Size = 114473 MB
    Interface = S-ATA
    Temperature = 30 C
    Health = 100%
    Performance = 100%
    Power on Time = 38 days, 11 hours
    Est. Lifetime = more than 1000 days
Run Code Online (Sandbox Code Playgroud)

四处乱逛,我也把代码缩小到:

def dataList = []
def theInfoFile = new File( 'testdata.txt' )

if( !theInfoFile.exists() ) {
  println "File does not exist"
} else {
  // Split the text of the file into blocks separated by \n\n
  // Then, starting with an empty list go through each block of text in turn
  dataList = theInfoFile.text.split( '\n\n' ).inject( [] ) { list, block ->
    // Split the current block into lines (based on the newline char)
    // Then starting with an empty map, go through each line in turn
    // when done, add this map to the list we created in the line above
    list << block.split( '\n' ).inject( [:] ) { map, line ->
      // Split the line up into a key and a value (trimming each element)
      def (key,value) = line.split( '\t: ' ).collect { it.trim() }
      // Then, add this key:value mapping to the map we created 2 lines above
      map << [ (key): value ] // The leftShift operator also returns the map 
                              // the inject closure has to return the accumulated
                              // state each time the closure is called
    }
  }
}

dataList.eachWithIndex { it, index ->
  println "Drive $index"
  it.each { k, v ->
    println "\t$k = $v"
  }
}
Run Code Online (Sandbox Code Playgroud)

但是必须立即将整个文件加载到内存中(并依赖于\nEOL终止字符)


Bla*_*ger 6

这是我的解决方案:

File file = new File('testdata.txt')
if(file.exists()) {
    def drives = [[:]]
    // Split each line using whitespace:whitespace as the delimeter.
    file.splitEachLine(/\s:\s/) { items ->
        // Lines that did not have the delimeter will have 1 item.
        // Add a new map to the end of the drives list.
        if(items.size() == 1 && drives[-1] != [:]) drives << [:]
        else {
            // Multiple assignment, items[0] => key and items[1] => value
            def (key, value) = items
            drives[-1][key] = value
        }
    }

    drives.eachWithIndex { drive, index ->
        println "Drive $index"
        drive.each {key, value ->
            println "\t$key: $value"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)