2

1 つのファイルは次のようになります。

BEGIN_META
    stuff
    to
    discard
END_META
BEGIN_DB
    header
    to
    discard

    data I
    wish to
    extract
 END_DB

catそれらすべてが一緒になった無限のストリームを解析できるようにしたいと思いますre.findall('something useful', '\n'.join(sys.stdin), re.M)

以下は私の試みですが、ジェネレーターを強制的に返さget_raw_table()なければならないため、要件に完全には適合しません。強制を削除すると、返されたジェネレーターが空かどうかをテストできないため、が空かどうかを確認できませんsys.stdin

def get_raw_table(it):
    state = 'begin'
    for line in it:
        if line.startswith('BEGIN_DB'):
            state = 'discard'
        elif line.startswith('END_DB'):
            return
        elif state is 'discard' and not line.strip():
            state = 'take'
        elif state is 'take' and line:
            yield line.strip().strip('#').split()

# raw_tables is a list (per file) of lists (per row) of lists (per column)
raw_tables = []
while True:
    result = list(get_raw_table(sys.stdin))
    if result:
        raw_tables.append(result)
    else:
        break
4

2 に答える 2

4

このようなものがうまくいくかもしれません:

import itertools

def chunks(it):
    while True:
        it = itertools.dropwhile(lambda x: 'BEGIN_DB' not in x, it)
        it = itertools.dropwhile(lambda x: x.strip(), it)
        next(it)
        yield itertools.takewhile(lambda x: 'END_DB' not in x, it)

例えば:

src = """
BEGIN_META
    stuff
    to
    discard
END_META
BEGIN_DB
    header
    to
    discard

    1data I
    1wish to
    1extract
 END_DB


BEGIN_META
    stuff
    to
    discard
END_META
BEGIN_DB
    header
    to
    discard

    2data I
    2wish to
    2extract
 END_DB
"""


src = iter(src.splitlines())
for chunk in chunks(src):
    for line in chunk:
        print line.strip()
    print
于 2013-02-07T08:59:20.960 に答える
1

関数をよりプログラム的に分離して、プログラミング ロジックをより意味のあるものにし、コードをよりモジュール化して柔軟にすることができます。のようなことを言わないようにしてください。

state = "some string"

将来、このモジュールに何かを追加したい場合はどうなるか、変数の「状態」が取るパラメーターと、値が変更されたときに何が起こるかを知る必要があるためです。この情報を覚えているとは限らず、面倒なことになる可能性があります。この動作を模倣する関数を作成すると、よりクリーンで実装が容易になります。

def read_stdin():
    with sys.stdin as f:
        for line in f:
            yield line

def search_line_for_start_db(line):
    if "BEGIN DB" in line:
        search_db_for_info()

def search_db_for_info()
    while "END_DB" not in new_line: 
        new_line = read_line.next()
        if not new_line.strip():
            # Put your information somewhere
            raw_tables.append(line)

read_line = read_stdin()
raw_tables = []
while True:
    try:
        search_line_for_start_db(read_line.next())
    Except: #Your stdin stream has finished being read
        break #end your program
于 2013-02-07T02:32:49.117 に答える