Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need the Groovy way to do partial file substitutions

Tags:

regex

groovy

I have a file that I need to modify. The part I need to modify (not the entire file), is similar to the properties shown below. The problem is that I only need to replace part of the "value", the "ConfigurablePart" if you will. I receive this file so can not control it's format.

alpha.beta.gamma.1 = constantPart1ConfigurablePart1
alpha.beta.gamma.2 = constantPart2ConfigurablePart2
alpha.beta.gamma.3 = constantPart3ConfigurablePart3

I made this work this way, though I know it is really bad!

def updateFile(String pattern, String updatedValue) {
    def myFile = new File(".", "inputs/fileInherited.txt")
    StringBuffer updatedFileText = new StringBuffer()
    def ls = System.getProperty('line.separator')
    myFile.eachLine{ line ->
        def regex = Pattern.compile(/$pattern/)
        def m = (line =~ regex)
        if (m.matches()) {
            def buf = new StringBuffer(line)
            buf.replace(m.start(1), m.end(1), updatedValue)
            line = buf.toString()
        }
        println line
        updatedFileText.append(line).append(ls)
    }
    myFile.write(updatedFileText.toString())
}

The passed in pattern is required to contain a group that is substituted in the StringBuffer. Does anyone know how this should really be done in Groovy?

EDIT -- to define the expected output

The file that contains the example lines needs to be updated such that the "ConfigurablePart" of each line is replaced with the updated text provided. For my ugly solution, I would need to call the method 3 times, once to replace ConfigurablePart1, once for ConfigurablePart2, and finally for ConfigurablePart3. There is likely a better approach to this too!!!

*UPDATED -- Answer that did what I really needed *

In case others ever hit a similar issue, the groovy code improvements I asked about are best reflected in the accepted answer. However, for my problem that did not quite solve my issues. As I needed to substitute only a portion of the matched lines, I needed to use back-references and groups. The only way I could make this work was to define a three-part regEx like:

(.*)(matchThisPart)(.*)

Once that was done, I was able to use:

it.replaceAdd(~/$pattern/, "\$1$replacement\$3")

Thanks to both replies - each helped me out a lot!

like image 986
JoeG Avatar asked Jun 04 '13 18:06

JoeG


2 Answers

It can be made more verbose with the use of closure as args. Here is how this can be done:

//abc.txt
abc.item.1 = someDummyItem1
abc.item.2 = someDummyItem2
abc.item.3 = someDummyItem3
alpha.beta.gamma.1 = constantPart1ConfigurablePart1
alpha.beta.gamma.2 = constantPart2ConfigurablePart2
alpha.beta.gamma.3 = constantPart3ConfigurablePart3
abc.item.4 = someDummyItem4
abc.item.5 = someDummyItem5
abc.item.6 = someDummyItem6

Groovy Code:-

//Replace the pattern in file and write to file sequentially.
def replacePatternInFile(file, Closure replaceText) {
    file.write(replaceText(file.text))
}

def file = new File('abc.txt')
def patternToFind = ~/ConfigurablePart/
def patternToReplace = 'NewItem'

//Call the method
replacePatternInFile(file){
    it.replaceAll(patternToFind, patternToReplace)
}

println file.getText()

//Prints:
abc.item.1 = someDummyItem1
abc.item.2 = someDummyItem2
abc.item.3 = someDummyItem3
alpha.beta.gamma.1 = constantPart1NewItem1
alpha.beta.gamma.2 = constantPart2NewItem2
alpha.beta.gamma.3 = constantPart3NewItem3
abc.item.4 = someDummyItem4
abc.item.5 = someDummyItem5
abc.item.6 = someDummyItem6

Confirm file abc.txt. I have not used the method updateFile() as done by you, but you can very well parameterize as below:-

def updateFile(file, patternToFind, patternToReplace){
   replacePatternInFile(file){
      it.replaceAll(patternToFind, patternToReplace)
   }
} 
like image 124
dmahapatro Avatar answered Oct 21 '22 10:10

dmahapatro


For a quick answer I'd just go this route:

patterns =  [pattern1 : constantPart1ConfigurablePart1,
     pattern2 : constantPart2ConfigurablePart2,
     pattern3 : constantPart3ConfigurablePart3]


def myFile = new File(".", "inputs/fileInherited.txt")
StringBuffer updatedFileText = new StringBuffer()
def ls = System.getProperty('line.separator')
myFile.eachLine{ line ->
    patterns.each { pattern, replacement ->
        line = line.replaceAll(pattern, replacement)
    }
    println line
    updatedFileText.append(line).append(ls)
}
myFile.write(updatedFileText.toString())
like image 3
BZ. Avatar answered Oct 21 '22 10:10

BZ.