Groovy parsing text file

前端 未结 2 532
醉话见心
醉话见心 2020-12-28 20:41

I have a file log that I would like to parse and am having some issues. At first it seemed it would be simple. I\'ll go ahead and post the source I have come up with and the

相关标签:
2条回答
  • This will read the data in blocks (with blank lines separating the blocks)

    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"
      }
    }
    

    Fingers crossed you have blank lines between your HDD info sections (you showed one in your test data) :-)

    btw: I get the following output:

    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
    

    Messing around, I also got the code down to:

    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"
      }
    }
    

    But that has to load the whole file into memory at once (and relies on \n as the EOL termination char)

    0 讨论(0)
  • 2020-12-28 21:18

    Here is my solution:

    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"
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题