Переформатирование кода с помощью регулярных выражений - PullRequest
6 голосов
/ 26 января 2010

У нас есть ArrayList предметов в нескольких классах, которые доставляют мне неприятности каждый раз, когда я хочу добавить новый предмет в список.С моей стороны было ошибкой спроектировать классы так, как я это делал, но изменение дизайна сейчас было бы более головной болью, чем стоит (бюрократическая модель водопада). Я должен был ожидать изменения формата документов, которые клиент поставлял нам водопадбудь проклят.

Я хотел бы написать простой скрипт на python, который входит в класс, добавляет элемент в список, а затем увеличивает все результаты поиска для следующих элементов.Это не очень объяснительно:

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) ); }
}

Вы видите, что если я хочу добавить значение между "Джейн" и "Бобом", мне нужно увеличивать целые числа в функциях Get *.Я просто хочу написать простой скрипт на Python, который сделает всю работу за меня.Кто-то, кого я очень уважаю, предложил регулярное выражение.

Редактировать:

Да, LinkedHashMap.Так просто, так легко и так не в спецификации дизайна сейчас.Я ненавижу водопад.Ненавижу это со страстью.Вся эта часть была «маленькой» и «легкой» частью, которая «не должна занимать много времени на разработку».Я сделал ошибки.Теперь он застрял в камне.

Ответы [ 4 ]

4 голосов
/ 26 января 2010

Комментарии о плохой практике отдельно - вот код, который вы спрашивали на языке, который вы просили. Лучше всего, если вы будете поддерживать систему таким образом, вероятно, было бы сделать так, чтобы эти java-файлы автоматически генерировались в самом процессе сборки - вы просто должны сохранить список имен в файле .txt в каталоге. Этот скрипт подходит для этого.

(Он не изменит ваши файлы, он создаст новые на основе шаблона, который вы разместили здесь)

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 голосов
/ 26 января 2010

Вы хотите, чтобы ваше регулярное выражение было таким же гибким, как и компилятор в отношении пробелов между токенами. Делая это и имитируя использование пробелов, вы делаете шаблон довольно грязным. Приведенный ниже код (извините: Perl, а не Python) редактирует ваши исходные файлы на месте.

#! /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; }
  }
}

Например,

$ ./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 голосов
/ 26 января 2010

Не делайте этого с регулярным выражением. Создайте символические константы (используя, например, перечисление), которые сопоставляют имена с числами.

0 голосов
/ 26 января 2010

Я делаю это (ну, что-то очень похожее) прямо сейчас, но с помощью макросов Excel и VBA.Все бизнес-ценности организованы и упорядочены в электронной таблице.Мне просто нужно нажать кнопку, чтобы сгенерировать соответствующий код для выбранных ячеек, а затем скопировать и вставить в IDE.Еще лучше, у меня есть несколько «столбцов кода» для каждой строки.Некоторые из них генерируют запросы, некоторые XSL-преобразования и некоторые процедуры.Для одной строки бизнес-данных я могу очень легко получить все три типа сгенерированного кода.

Я обнаружил, что это (повторное генерирование) НАМНОГО проще, чем переформатирование имеющегося у меня кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...