awk в python: как использовать сценарии awk в классе python?

Я пытаюсь запустить awk-скрипт с помощью python, чтобы обработать некоторые данные.

Есть ли способ запустить скрипт awk в классе python без использования системного класса для вызова его как процесса оболочки? Фреймворк, в котором я запускаю эти скрипты Python, не позволяет использовать вызов подпроцесса, поэтому я застрял либо в поиске способа конвертировать мой скрипт awk в python, либо, если это возможно, запустить скрипт awk в python.

Какие-либо предложения? Мой awk-скрипт в основном читает текстовый файл и изолирует блоки белков, которые содержат определенное химическое соединение (вывод генерируется нашей структурой; я добавил пример того, как это выглядит ниже) и изолирует их, распечатывая их на другой файл.

    buildProtein compoundA compoundB
    begin fusion
    Calculate : (lots of text here on multiple lines)
    (more lines)
    Final result - H20: value CO2: value Compound: value 
    Other Compounds X: Value Y: value Z:value

    [...another similar block]

Так, например, если я создаю белок и мне нужно посмотреть, есть ли в соединениях CH3COOH в строке конечного результата, если это так, я должен взять весь блок, начиная с команды «buildProtein», до начала следующий блок; и сохраните его в файле; а затем перейти к следующему и посмотреть, есть ли в нем снова соединение, которое я ищу... если его нет, я перехожу к следующему, до конца файла (в файле есть несколько вхождений соединения, которое Я ищу, иногда они смежные, а иногда чередуются с блоками, не имеющими соединения.

Любая помощь более чем приветствуется; уже несколько недель бью головой, и, узнав об этом сайте, я решил попросить о помощи.

Заранее спасибо за вашу доброту!


person user1006198    schedule 20.10.2011    source источник


Ответы (3)


Если вы не можете использовать модуль subprocess, лучше всего перекодировать скрипт AWK на Python. С этой целью модуль fileinput является отличным инструментом перехода с интерфейсом, подобным AWK.

person Raymond Hettinger    schedule 20.10.2011
comment
Большое спасибо Рэймонд. Должен ли я затем загрузить весь файл, обработать его с помощью ввода файла, а затем сохранить вывод во внешнем файле? Я предполагаю, что найти подходящий пример для моего довольно уникального случая сложно :) - person user1006198; 21.10.2011
comment
@ user1006198: Ваш случай не уникален. Просто ваш дизайн плохой, потому что AWK такой плохой. Загрузите весь файл. Обработать весь файл. Сохраните весь вывод. Полностью отказаться от AWK. Начните только с соответствующих вычислений и игнорируйте артефакты ограничений AWK. Python (во многих отношениях) будет проще. Поскольку это новое, конечно, вы должны сначала изучить его, что делает его сложным. - person S.Lott; 21.10.2011
comment
:-) Fileinput позволит вам обрабатывать ввод построчно, как это делает AWK. Вы можете отправить вывод в другой файл с помощью команды print ›› somefile, some_line_of_text. - person Raymond Hettinger; 21.10.2011
comment
Я понимаю; Я не знал об этом модуле, и теперь, читая, как он работает, он кажется очень похожим; спасибо, что указали на это, Раймонд! - person user1006198; 21.10.2011
comment
@S.Lott: Действительно, я понимаю, что дизайн плохой, но я не могу просто пойти к своей команде и сказать, что мы должны делать все с нуля; поэтому я пытаюсь перейти, не отказываясь от всего, что было сделано раньше ... если возможно, я хотел бы иметь упорядоченный список вместо ввода txt или, что еще лучше, объект, который я могу проанализировать в классе; но я не настолько хорош, чтобы написать порт с сборки (это то, что наше оборудование использует для экспортера) на python или C++, поэтому я должен полагаться на команду оборудования, чтобы написать его, и это занимает время, как вы можете себе представить :) - person user1006198; 21.10.2011
comment
@ user1006198: Я не могу просто пойти к своей команде и сказать, что мы должны делать все с нуля? Почему бы и нет? На самом деле вам придется переписывать все с нуля. Зачем лгать об этом? - person S.Lott; 21.10.2011
comment
вопрос логистики и времени; во-первых, я пишу простой парсер для журналов; другой - изменить свою сторону, чтобы сделать другой вывод :) - person user1006198; 25.10.2011

модуль Python re может помочь, или, если вас не беспокоят регулярные выражения и просто нужно быстро разделить поля, вы можете использовать встроенный str .split() и .find().

person Aphex    schedule 20.10.2011
comment
Спасибо, Афекс; пытался написать RE, но с треском провалился; так как я не слишком много знаю о чистом RE; с AWK легко найти и изолировать блоки, так как вы можете работать с оператором print и выключать его, но с чистым RE я не совсем уверен, как с этим бороться. Основная цель состоит в том, чтобы найти вхождение соединения в блоке и сохранить весь блок, если соединение есть в нем, поэтому для этого требуется не только найти что-то в блоке (это было бы достаточно легко для меня), но один раз вы находите вхождение, получаете все от первой строки до первой строки следующего блока и т.д. - person user1006198; 21.10.2011
comment
@user1006198: Комментарии — ужасное место для объяснения вашей настоящей проблемы. Попробуйте обновить свой вопрос, чтобы объяснить вашу проблему. Примеры помогают. Конструкция /pattern/ code в Awk использует RE. В Python это переводится как if re.match(r'pattern',line): code. Немного больше знаков препинания, чем в AWK. Тот же язык регулярных выражений в шаблоне. - person S.Lott; 21.10.2011
comment
Кроме того, во время моего краткого пребывания в качестве администратора UNIX я больше всего использовал awk для разделения полей, например, в awk -F ',' для разделения полей, разделенных запятыми, и так далее. Это тоже можно легко сделать в python, просто прочитав файл с readlines() и перебирая каждую строку и используя .split(). - person Aphex; 21.10.2011
comment
В самом деле сложно добавлять информацию в комментарии; вот почему я сделал все возможное, чтобы изложить свою проблему в основном посте; если это неясно, пожалуйста, дайте мне знать, и я буду более чем счастлив сделать его более читабельным (английский не мой родной язык, я стараюсь изо всех сил) - person user1006198; 25.10.2011

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

class ProteinIterator():
    def __init__(self, file):
        self.file = open(file, 'r')
        self.first_line = self.file.readline()
    def __iter__(self):
        return self
    def __next__(self):
        "returns the next protein build"
        if not self.first_line:     # reached end of file
            raise StopIteration
        file = self.file
        protein_data = [self.first_line]
        while True:
            line = file.readline()
            if line.startswith('buildProtein ') or not line:
                self.first_line = line
                break
            protein_data.append(line)
        return Protein(protein_data)

class Protein():
    def __init__(self, data):
        self._data = data
        for line in data:
            if line.startswith('buildProtein '):
                self.initial_compounds = tuple(line[13:].split())
            elif line.startswith('Final result - '):
                pieces = line[15:].split()[::2]   # every other piece is a name
                self.final_compounds = tuple([p[:-1] for p in pieces])
            elif line.startswith('Other Compounds '):
                pieces = line[16:].split()[::2]   # every other piece is a name
                self.other_compounds = tuple([p[:-1] for p in pieces])
    def __repr__(self):
        return ("Protein(%s)"% self._data[0])
    @property
    def data(self):
        return ''.join(self._data)

Здесь у нас есть итератор для текстового файла buildprotein, который возвращает по одному белку за раз как объект Protein. Этот Protein объект достаточно умен, чтобы знать свои входные данные, окончательные результаты и другие результаты. Возможно, вам придется изменить часть кода, если фактический текст в файле не совсем соответствует тому, что представлено в вопросе. Ниже приведен краткий тест кода с примером использования:

if __name__ == '__main__':
    test_data = """\
buildProtein compoundA compoundB
begin fusion
Calculate : (lots of text here on multiple lines)
(more lines)
Final result - H20: value CO2: value Compound: value 
Other Compounds X: Value Y: value Z: value"""

    open('testPI.txt', 'w').write(test_data)
    for protein in ProteinIterator('testPI.txt'):
        print(protein.initial_compounds)
        print(protein.final_compounds)
        print(protein.other_compounds)
        print()
        if 'CO2' in protein.final_compounds:
            print(protein.data)

Я не стал сохранять значения, но вы можете добавить их, если хотите. Надеюсь, это поможет вам.

person Ethan Furman    schedule 05.11.2011