Regular Expression Reformatting Code

We have an ArrayList elements in several classes that bring me problems every time I would like to insert a new element into the list. For my part, it was a mistake to design the classes as I did, but changing the design will now be more of a headache than worth it (bureaucratic model of the waterfall). I had to anticipate the format changes in the documents that the client supplied us with the waterfall to be damned.

I would like to write a simple python script that goes into the class, adds an item to the list, and then increments all the search results for the following elements. This is not very revealing:

 Foo extends Bar{ public Foo(){ m_Tags.add("Jane"); m_Tags.add("Bob"); m_Tags.add("Jim"); } public String GetJane() { return m_ParsedValue.get( m_Tags.get(1) ); } public String GetBob() { return m_ParsedValue.get( m_Tags.get(2) ); } public String GetJim() { return m_ParsedValue.get( m_Tags.get(3) ); } } 

You see, if I want to add a value between "Jane" and "Bob", then I need to increase the number of integers in the Get * functions. I just want to write a simple script in Python that does this work for me. Someone whom I respect a lot was offering a regular expression.

Edit:

Yes, LinkedHashMap. So simple, so simple and so not in design now. I hate the waterfall. I hate this with passion. This whole bit was the "small" and "easy" part, which "should not spend a lot of time on development." I made mistakes. Now he is stuck in stone.

+6
java python regex perl
source share
4 answers

You want your regex to be as flexible as the compiler with regard to spaces between tokens. Doing this and emulating the use of spaces makes the template pretty messy. The code below (sorry: Perl, not Python) edits the source files in place.

 #! /usr/bin/perl -i.bak use warnings; use strict; my $template = '^( public String Get)(\w+)( \( \) { return m_ParsedValue . get \( m_Tags . get \( )(\d+)( \) \) ; } )$'; $template =~ s/ +/\\s*/g; $template =~ s/(\r?\n)+/\\s+/g; my $getter = qr/$template/x; die "Usage: $0 after new-name source ..\n" unless @ARGV >= 3; my $after = shift; my $add = shift; my $index; while (<>) { unless (/$getter/) { print; next; } my($abc,$name,$lmno,$i,$xyz) = ($1,$2,$3,$4,$5); if (defined $index) { print join "" => $abc, $name, $lmno, ++$index, $xyz; } else { if ($name eq $after) { $index = $i; print; print join "" => $abc, $add, $lmno, ++$index, $xyz; } else { print; } } } 

For example,

  $ ./add-after Jane Foo code.java
 $ cat code.java
 Foo extends Bar {
     public Foo () {
         m_Tags.add ("Jane");
         m_Tags.add ("Bob");
         m_Tags.add ("Jim");
     }

     public String GetJane () {return m_ParsedValue.get (m_Tags.get (1));  }
     public String GetFoo () {return m_ParsedValue.get (m_Tags.get (2));  }
     public String GetBob () {return m_ParsedValue.get (m_Tags.get (3));  }
     public String GetJim () {return m_ParsedValue.get (m_Tags.get (4));  }
 } 
+4
source share

Do not do this with regex. Create symbolic constants (using, for example, an enumeration) that map names to numbers.

+4
source share

Comments about different practices - here is the code that you asked in the language you requested. Best of all, if you support the system this way, it would probably make these java files automatically generated during the build process - you just save the list of names in a TXT file in a directory. This script is suitable for this.

(It will not modify your files, it will generate new ones based on the template that you posted here)

 import re, sys template = """Foo extends Bar{ public Foo(){ %s } %s } """ tag_templ = """ m_Tags.add("%s");""" getter_templ = """ public String GetJane() { return m_ParsedValue.get( m_Tags.get(%d) ); }""" def parse_names(filename): data = open(filename).read() names = re.findall(r'm_Tags\.add\("(.*?)"', data) return names def create_file(filename, names): tag_lines = [tag_templ % name for name in names] getter_lines = [getter_templ % (i + 1) for i in range(len(names))] code = template % ("\n".join(tag_lines), "\n".join(getter_lines)) file = open(filename,"wt") file.write(code) file.close() def insert_name(after, new_name, names): names.insert(names.index(after) + 1, new_name) if __name__ == "__main__": if len(sys.argv ) < 4: sys.stderr.write("Usage: changer.py <filename> <name-before-insertion> <new-name>") sys.exit(1) filename, name_before, new_name = sys.argv[1:] names = parse_names(filename) insert_name(name_before, new_name, names) create_file(filename, names) 
+4
source share

I'm doing this (well, something very similar) right now, but using Excel and VBA macros. All business values ​​are organized and ordered in a spreadsheet. I just need to click a button to create the appropriate code for the selected cells, and then copy-paste into the IDE. Even better, I have several β€œcolumns of code” for each row. Some of them generate queries, some XSL transformations, and some procedures. For a single line of business data, I can easily get all three types of generated code.

I found that it (generating) is a lot easier than reformatting the existing code that I had.

0
source share

All Articles