2012-11-30 21 views
5

Python nghiệp dư ở đây. Tôi có một tập tin văn bản liệt kê thông tin trên hàng ngàn dòng và tôi đang cố gắng chọn một dòng và 2-3 dòng sau dựa trên việc chúng có khớp với một mẫu hay không. Tôi đã lọc các tập tin xuống từ bản gốc để chỉ chứa các bộ phận của tập tin quan tâm đến tôi như vậy tập tin hiện tại của tôi trông như thế này:Vấn đề với việc chọn nhiều dòng của tài liệu txt và ghi vào tài liệu văn bản mới trong python

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 

và vân vân và vân vân ... Về cơ bản những gì Tôi đang cố gắng làm là viết tất cả các dòng có chứa phần silence.wav của dòng và sau đó hai dòng tiếp theo sau nó. Tôi sử dụng đoạn mã sau:

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() 

này hoạt động tốt cho hầu hết các phần vì nó in dòng silence.wav và dòng trong đó có các phản ứng (phần tôi quan tâm nhất, các trig1 trước một phản ứng tại thời điểm này là ít quan trọng). Tuy nhiên, vấn đề tôi gặp phải là khi các đường đi:

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

Kể từ đầu ra của tôi sau đó sẽ viết stim3 (dòng hiện) và stim5 (dòng tiếp theo sau khi bỏ qua trig1), tôi nghĩ rằng nó chuyển sang tiếp theo "stim: silence.wav" và bỏ qua kích thích5 vì nó được đưa vào lệnh trước đó khi nó được viết. Tôi muốn trig6.RESP: 1 sau khi kích thích5 nhưng đầu ra của tôi không hiển thị nó vì lý do đó tôi mô tả. Có cách nào tôi có thể làm cho nó không bỏ qua kích thích5?

Xin lỗi nếu điều này thực sự dài. Cảm ơn bạn trước!

+0

Lề nhỏ: Tôi khuyên bạn nên đóng tất cả các tệp bạn đã mở. Cách tốt nhất để làm điều đó - sử dụng câu lệnh 'with'. – cleg

Trả lời

4

Làm thế nào về một cái gì đó như thế này? (hoàn toàn chưa được kiểm tra)

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

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

Nó không ưa thích, nhưng tôi nghĩ rằng nó nên được khá mạnh mẽ.

+0

Ôi trời ơi, thật là đơn giản. Nó cũng hoạt động! Cảm ơn bạn, cảm ơn bạn, cảm ơn bạn! – user1867442

1

Một cách tiếp cận có thể sẽ được sử dụng một deque để bạn có thể theo dõi ba dòng tại một thời điểm:

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() 

Nếu bạn cung cấp maxlen tham số để deque, sau đó khi bạn thêm các yếu tố bổ sung cho một kết thúc một phần tử được popped tắt của bên kia, ví dụ:

>>> 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) 

này cho phép bạn duyệt qua các tập tin nhưng tiết kiệm 3 dòng cuối cùng mà bạn đọc trong một cách thuận tiện, bất cứ lúc nào các yếu tố đầu tiên của window phù hợp với điều kiện của bạn, chỉ cần xuất ra dòng phù hợp và hai sau miễn là chúng không phù hợp với điều kiện của bạn.

+0

Đây là thông minh, nhưng nó sẽ không viết một số dòng hai lần ?, Ngoài ra, có lẽ nên có một kiểm tra ở cuối vòng lặp để đảm bảo rằng thứ hai đến dòng cuối cùng không nên kích hoạt một ghi. – mgilson

+0

Chỉ cần chỉnh sửa để giải quyết những vấn đề đó, tôi không thể nói từ câu hỏi liệu các dòng trùng lặp có được mong muốn hay không, nhưng chúng có lẽ không nên ở đó. –

+0

Vui lòng bỏ qua nhận xét của tôi (hiện đã bị xóa). Nó không chính xác. – mgilson

2

nỗ lực của tôi tại dịch này để psuedocode nói:

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

(Hãy để chính xác cho tôi ở đây)

Bạn đang thiếu các Trig6 bởi vì bạn đang yêu cầu cho các dòng tiếp theo mà doesn' t tồn tại. Bạn có thể viết lại nó, nơi bạn giới thiệu ngược thay vì tiền đạo và có sửa chữa vấn đề của bạn?

1

Bạn thực sự nên học cách sử dụng cụm từ thông dụng (mô đun)
Bắt buộc phải phân tích văn bản là bắt buộc.

Xem những gì nó cho phép để làm:

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 

kết quả

('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') 

và sau đó bạn làm những gì bạn muốn với những tuples dòng

pat là một chuỗi được sử dụng như một mẫu để xác định một regex.
RE là một regex biên soạn, nó là một đối tượng trong đó có phương pháp tìm kiếm, trận đấu, findall, vv

ngoặc () xác định một nhóm.
Một nhóm chụp một số phần văn bản nhất định. Nhưng (?: ) xác định một nhóm không nắm bắt được phần văn bản phù hợp. Sẽ hữu ích khi hành động trên phần văn bản, ví dụ như đặt các vòng loại * hoặc ? hoặc + vào cuối nhóm.

Khi dòng thứ ba có 'silence.wav', dòng thứ ba vẫn chưa được so khớp, và khi dòng thứ hai có 'silence.wav', chỉ dòng đầu tiên phải khớp. Đó là lý do tại sao có phần (?.*silence.wav) ở hai vị trí trong mẫu.

^ là một dấu hiệu có nghĩa là 'sự khởi đầu của chuỗi'
^ với cờ 'khởi đầu của một dòng' re.MULTILINE phương tiện

Các phần (?<!) * của mô hình đang có để không nắm bắt những khoảng trống ở phần cuối của dòng.

Điểm . trong một mô hình nghĩa là 'bất kỳ ký tự', ngoại trừ nhân vật LF

\n 

Và điểm khác, mà tôi có thể trả lời bạn nếu bạn cần.

+0

Cảm ơn bạn đã đề xuất. Tôi nghĩ bạn cũng đúng. Bước tiếp theo, tìm hiểu các biểu thức chính quy. Hiểu rồi. :) – user1867442

Các vấn đề liên quan