Как сделать многострочный поиск и замену скриптом?

Я пытаюсь заменить каждый многострочный импорт внутри исходного файла Python. Итак, источник выглядит так:

from XXX import (
   AAA,
   BBB,
)
from YYY import (
   CCC,
   DDD,
   EEE,
   ...
)
...other instructions...

и я хотел бы получить что-то вроде

from XXX import AAA, BBB
from YYY import CCC, DDD, EEE, ...
...other instructions...

Я пытался использовать sed, но похоже, что он не поддерживает нежадное сопоставление закрывающей скобки, поэтому он "съедает" второй импорт.. :(
Любой намек? Это невозможно с sed? Должен ли я попробовать другим инструментом?


person Joril    schedule 15.12.2008    source источник
comment
после «импорта» всегда есть 2 токена или они переменные?   -  person Gishu    schedule 15.12.2008
comment
Мне было интересно, можно ли это сделать с помощью одного регулярного выражения :)   -  person Gishu    schedule 15.12.2008
comment
Они переменные.. Извините, уточню вопрос :)   -  person Joril    schedule 15.12.2008


Ответы (3)


Эммм... что не так с Python?

lineIter= iter(aFile)
for aLine in lineIter:
    if aLine.startswith("import"):
        if aLine.endswith("("):
            for aModule in lineIter:
                if aModule.endwith(")"):
                    break
                print "import", aModule.strip()
        else:
            print aLine.stri()
    else:
        print aLine.strip()
person S.Lott    schedule 15.12.2008
comment
Не в каждой системе он установлен? Конечно, многие машины, на которых я работаю, этого не делают. - person GodEater; 15.12.2008
comment
Брайан, поскольку он хочет изменить исходный файл Python, держу пари, что у него есть доступ к какой-то машине с установленным Python :) - person Svante; 15.12.2008
comment
С Python все в порядке :) Я пытался использовать sed, потому что он выглядел как подходящий инструмент для этой задачи :) - person Joril; 15.12.2008
comment
@Joril: sed сложно использовать (как вы заметили). Следовательно, это не совсем подходящий инструмент для решения задачи, не так ли? - person S.Lott; 15.12.2008
comment
Ну, это было бы, если бы у него была поддержка нежадного сопоставления :) Но я этого не знал Х-) - person Joril; 15.12.2008
comment
@Joril: Я не согласен - если нежадное сопоставление неочевидно, его слишком сложно использовать. И для большинства задач, подобных этой, на самом деле не имеет смысла сводить процесс к нескольким загадочным строкам непонятного sed. - person S.Lott; 15.12.2008
comment
Я понимаю вашу точку зрения ... выражения sed часто в некоторой степени предназначены только для записи: D Но я все еще нахожу это очень удобным для небольших задач (конечно, не таких, как эта). Спасибо за то, что поделились своими мыслями! :) - person Joril; 15.12.2008
comment
stackoverflow.com/questions/366980/ - не видит значение в sed. Раньше использовал sed. Отказался от него, потому что Python всегда казался лучше. - person S.Lott; 15.12.2008

Это может сработать для вас:

sed '/^from/,/^)/{H;//{x;/)/{s/[\n()]//g;s/  */ /g;s/,$//;p;x}};d}' source
from XXX import AAA, BBB
from YYY import CCC, DDD, EEE, ...
...other instructions...
person potong    schedule 22.12.2011

Для потомков, вот несколько отшлифованная версия скрипта С.Лотта (я бы поместил ее в качестве комментария, но она слишком длинная ^^; ). Эта версия сохраняет отступы и дает результат, более близкий к моему примеру.

lineIter=iter(aFile)
for aLine in lineIter:
    s = aLine.strip()
    if s.startswith("from ") and s.endswith("("):
        complete = s[:-1]
        for aModule in lineIter:
            m = aModule.strip()
            if m.endswith(")"):
                break
            complete += m.strip()
        print complete
    else:
        print aLine,
person Joril    schedule 15.12.2008