LINUX.ORG.RU

Как сделать в python как в awk

 ,


1

1

Привет! ЛОР, есть у меня скриптик, настраивающий com-порты в линуксе. Есть там такая строчка

cat tmpfile |awk '/NetMos/,/serial/'
В tmpfile перед этим пишется инфа из lspci, если в выхлопе содержится фраза «NetMos». Далее, соответственно, вынимает инфу по этой NetMos и парсим ее. Вынимается информация начиная с первого NetMos и заканчивая последним словом serial.

А как сделать в python то же самое, что делает эта строчка с использованием awk?

★★

Если содержимое файла можно прочитать целиком, то можно использовать регулярки:

# -*- coding: utf-8 -*-
#!/usr/bin/env python

import re

def parse(text):
  regex = re.compile(r'\bNetMos\b(.*)\bserial\b', flags = re.M | re.S)
  match = regex.search(text)
  if match:
    return match.group(1)

text = '''
NetMos foo

bar

NetMos serial

end serial foo'''

print parse(text)

==>

 foo

bar

NetMos serial

end 
theNamelessOne ★★★★★
()
import sys
prt = False
for i in file('tmpfile'):
    if 'NetMos' in i : prt = True
    if 'serial' in i : sys.stdout.write(i) ; prt = False
    if prt: sys.stdout.write(i)
at ★★
()
Последнее исправление: at (всего исправлений: 1)
Ответ на: комментарий от schizoid

А зачем так много букофф?

print '\n'.join([ s[s.find('NetMos'):s.rfind('serial')+len('serial')] for s in open('tmpfile') if 'NetMos' in s and 'serial' in s ])
ФП рулит!;-)

AIv ★★★★★
()
Ответ на: комментарий от AIv

Блин, опередил)

У меня так вышло:

import re
print('\n'.join(re.search(r'NetMos(?P<a>.*)serial.*', s).group(1) for s in open('tmpfile') if re.match('.*NetMos.*serial.*', s)))
Hope ★★
()
Ответ на: комментарий от Kalashnikov

Так я и пишу с начала. Питон я, можно сказать, не знаю, поэтому и спрашиваю, с использованием чего можно сделать на питоне аналогичное действие. Или это тоже путь к говнокоду?

kir64 ★★
() автор топика
Ответ на: комментарий от AIv

Да, разница невооружённым глазом видна

$ cat test.py 
with open('tmpfile') as f:
	s = f.read()
	if 'NetMos' in s and 'serial' in s:
		print s[s.find('NetMos'):s.rfind('serial')+len('serial')]
$ cat test_fp.py 
print '\n'.join([ s[s.find('NetMos'):s.rfind('serial')+len('serial')] for s in open('tmpfile') if 'NetMos' in s and 'serial' in s ])
$ wc -c test.py test_fp.py 
138 test.py
133 test_fp.py
schizoid ★★★
()
Ответ на: комментарий от xpahos

С каких пор list comprehensions стал ФП?

С тех пор, как его стали позиционировать как замену map?

ну и второй вопрос: зачем делать из python perl?

В жизни не писал на перле. Но так короче (по числу стро так вчетверо), и ИМНО наглядней.

AIv ★★★★★
()
Ответ на: комментарий от AIv

С тех пор, как его стали позиционировать как замену map?

o.0 кто? когда?

В жизни не писал на перле. Но так короче (по числу стро так вчетверо), и ИМНО наглядней.

т прнс?

xpahos ★★★★★
()
Ответ на: комментарий от xpahos

o.0 кто? когда?

Да есть один лошара, Дэвидом зовут. В своей жалкой книжонке «Python. Подробный справочник. 4е издание» Ч1 гл 6 «Функциональное программирование» (во лох!) параграф «генераторы списков», стр 148. вон какую ересь пишет:

Генераторы списков
На практике достаточно часто возникает необходимость применить неко-
торую функцию ко всем элементам списка, чтобы создать новый список
с результатами. Например:
nums = [1, 2, 3, 4, 5]
squares = []
for n in nums:
squares.append(n * n)
Так как потребность в подобной операции возникает очень часто, она была
реализована в виде оператора, который называется генератором списков.

Вы ему обязательно напишите что он неправ! А то пацаны и не знают...

т прнс?

И да и нет. Скорее нет, чем да.

AIv ★★★★★
()
Ответ на: комментарий от xpahos

Зачем? там есть как [] так и (), кроме того ленивость не является обязательным требованием для функциональности.

AIv ★★★★★
()
Ответ на: комментарий от kir64

Вообще, мое решение не очень хорошее, т.к. оно требует, чтобы весь файл был прочитан за раз. Лучше сделать через простой автомат:

# -*- coding: utf-8 -*-
#!/usr/bin/env python

from __future__ import print_function

import re
import sys

START_RE = re.compile(r'\bNetMos\b(.*)')
END_RE = re.compile(r'(.*)\b(serial\b.*)')

def parse(infile=sys.stdin, outfile=sys.stdout):
  match_started = False
  buf = ''
  for line in infile:
    if not match_started:
      match = START_RE.search(line)

      if match:
        match_started = True
        buf += match.group(1)
    else:
      match = END_RE.search(line)

      if match:
        buf += match.group(1)
        print(buf, end='', file=outfile)
        buf = match.group(2)
      else:
        buf += line

if __name__ == '__main__':
  try:
    parse()
  except Exception as e:
    print(e, file=sys.stderr)
theNamelessOne ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.