5

Pythonアマチュアです。何千行もの情報をリストしたテキスト ファイルがあり、パターンに一致するかどうかに基づいて、行と次の 2 ~ 3 行を選択しようとしています。元のファイルからファイルをフィルタリングして、ファイルの関心のある部分だけを含めるようにしたので、現在のファイルは次のようになります。

trig1.RESP: 
stim4: silence.wav 
trig1.RESP: 
trig6.RESP: 1 
trig1.RESP:
trig1.RESP: 
trig5.RESP: 1
stim5: silence.wav
trig1.RESP:
trig6.RESP: 1
stim3: silence.wav
trig1.RESP:
stim5: silence.wav
trig1.RESP:
trig6.RESP: 1

などなど... 基本的に私がやろうとしているのは、行の Silence.wav 部分を含むすべての行を書き、その後に続く 2 行を書くことです。次のコードを使用しました。

parsed_output = open("name-of-file-to-be-written", "w")
filtered_input = open("name-of-file-that-has-above-data", "r")
for line in filtered_input:
    if "silence.wav" in line and "trig1" in filtered_input.next():
        parsed_output.write(line)
        parsed_output.write(filtered_input.next())
parsed_output.close()

これは、silence.wav 行と応答のある行を出力するため、ほとんどの場合うまく機能します (私が最も興味を持っている部分、この時点での応答の前の trig1 はあまり重要ではありません)。しかし、私が遭遇する問題は、行が行くときです:

stim3: silence.wav
trig1.RESP: 
stim5: silence.wav

私の出力は stim3 (現在の行) と stim5 (trig1 をスキップした後の次の行) を書き込むので、次の "stim:silence.wav" に移動し、前のコマンドに含まれていた stim5 をスキップすると思います。それが書かれたとき。stim5 の後に trig6.RESP: 1 が必要ですが、説明した理由で出力に表示されません。そのstim5をスキップしないようにする方法はありますか?

これが本当に長い場合は申し訳ありません。前もって感謝します!

4

4 に答える 4

4

このようなものはどうですか?(完全に未テスト)

count = 3
for line in filtered_input:
    if "silence.wav" in line:
        count = 0
    else:
        count += 1

    if count <= 2:
        filtered_output.write(line)

派手ではありませんが、かなり頑丈であるべきだと思います。

于 2012-11-30T21:02:18.337 に答える
2

これを擬似コードに翻訳しようとすると、次のようになります。

For each (Line) {
      If Next Line is "Trig1" AND Current Line is "silence.wav"
          Log it
}
## And We're Done

(ここで私を修正してください)

存在しない次の行を求めているため、Trig6 がありません。前方ではなく後方を参照するように書き直して、問題を解決してもらえますか?

于 2012-11-30T21:08:30.177 に答える
1

考えられるアプローチの 1 つは、dequeを使用して、一度に 3 行を追跡できるようにすることです。

import collections

parsed_output = open("name-of-file-to-be-written", "w")
filtered_input = open("name-of-file-that-has-above-data", "r")

window = collections.deque([None]*3, maxlen=3)
for line in filtered_input:
    window.append(line)
    if 'silence.wav' in window[0]:
        parsed_output.write(window[0])
        # only output next two lines if they don't also contain 'silence.wav'
        if 'silence.wav' not in window[1]:
            parsed_output.write(window[1])
            if 'silence.wav' not in window[2]:
                parsed_output.write(window[2])
# following if/elif in case last or second to last line contain 'silence.wav'
if 'silence.wav' in window[1]:
    parsed_output.write(window[1])
    parsed_output.write(window[2])
elif 'silence.wav' in window[2]:
    parsed_output.write(window[2])
parsed_output.close()

パラメータを deque に指定するmaxlenと、要素を一方の端に追加すると、要素が他方の端からポップされます。次に例を示します。

>>> x = collections.deque([1, 2, 3], maxlen=3)
>>> x
deque([1, 2, 3], maxlen=3)
>>> x.append(4)
>>> x
deque([2, 3, 4], maxlen=3)
>>> x.append(5)
>>> x
deque([3, 4, 5], maxlen=3)

これにより、ファイルを反復処理できますが、便利な方法で読み取った最後の 3 行を保存できますwindow。あなたのコンディションに合わせます。

于 2012-11-30T21:07:03.677 に答える
1

あなたは本当に正規表現の使い方を学ぶべきです (モジュール re)
テキストを分析したいときは必須です。

それができることを見てください:

import re

ss = """trig1.RESP: 
stim4: silence.wav 
trig1.RESP: 
trig6.RESP: 1 
trig1.RESP:
trig1.RESP: 
trig5.RESP: 1
stim5: silence.wav
trig1.RESP:
trig6.RESP: 1
stim3: silence.wav
trig1.RESP:
stim5: silence.wav
trig1.RESP:
trig6.RESP: 1

stim777: silence.wav
stim111: silence.wav 
trig1.RESP: 
trig6.RESP: 1
trig1.RESP: 
trig6.RESP: 1"""

pat = ('^(.+silence.wav.*)(?<! ) *\n'
       '(?:(?!.*silence.wav)(.*)(?<! ) *\n)?'
       '(?:(?!.*silence.wav)(.*)(?<! ) *)?')

RE = re.compile(pat,re.MULTILINE)

for tugr in RE.findall(ss):
    print tugr

結果

('stim4: silence.wav', 'trig1.RESP:', 'trig6.RESP: 1')
('stim5: silence.wav', 'trig1.RESP:', 'trig6.RESP: 1')
('stim3: silence.wav', 'trig1.RESP:', '')
('stim5: silence.wav', 'trig1.RESP:', 'trig6.RESP: 1')
('stim777: silence.wav', '', '')
('stim111: silence.wav', 'trig1.RESP:', 'trig6.RESP: 1')

そして、これらの行のタプルでやりたいことをします

patは、正規表現を定義するためのパターンとして使用される文字列です。
REはコンパイルされた正規表現であり、 searchmatchfindallなど のメソッドを持つオブジェクトです

括弧( )はグループを定義します。
グループは、テキストの特定の部分をキャプチャします。ただし(?: )、一致するテキストの部分をキャッチしないグループを定義します。グループの末尾に修飾子*?またはを配置するなど、テキストの一部を操作すると便利です。+

3 行目に「silence.wav」がある場合は不一致のままにし、2 行目に「silence.wav」がある場合は 1 行目のみ一致する必要があります。そのため柄の部分(?.*silence.wav)が2箇所あります。

^は「文字列の開始」を意味する記号
^で、フラグre.MULTILINE は「行の開始」を意味します

パターンの部分(?<! ) *は、行末の空白をキャッチしないようにするためのものです。

パターン内のポイント.は、LF 文字を除く「任意の文字」を意味します

\n

その他、必要に応じてお答えします。

于 2012-11-30T21:27:21.553 に答える