0

I want to process some text files and detect last line of each one to do some operations at that point. In this simplified example, print file name, number of total lines and the odd ones. Assuming following content of files:

==> file1 <==
one
two
three

==> file2 <==
monday
tuesday
wednesday
thursday

==> file3 <==
red
green
blue

This is how I would implement it in perl:

#!/usr/bin/env perl

use strict;
use warnings;

my (@odd);

while ( <> ) {
        print $_;
        if ( $. & 1 ) {
                chomp;
                push @odd, $_;
        }
        if ( eof ) {
                print $ARGV, ' -- ', $., "\n";
                print 'Odd lines => ', join( ':', @odd ), "\n";
                undef @odd;
                close ARGV;
        }
}

For those who are not used to it, <> is similar to fileinput.input()and ARGV is the filehandle that I close explicitly to reset the line number counter ($.). I hope it's easy to understand. The key part is the check of eof.

But this is how I try to do it with python:

#!/usr/bin/env python3

from fileinput import *

fname = ''
lnumber = 0
odd = []
try:
    for line in input():   
        if filelineno() == 1 and fname:
            print('{0} -- {1}'.format(fname, lnumber))
            print('Odd lines => {0}'.format(':'.join(odd)))
            odd = []
            fname = ''
            lnumber = 0
        lnumber += 1
        print('{0}'.format(line), end='')
        if lnumber & 1:
            odd.append(line.rstrip())
        if not fname:
            fname = filename()
        if not line:
            print('Is this end of line??')
except OSError as e:
    print('Operation failed: {0}'.format(e.strerror))
except EOFError as e:
    print('EOF found: {0}'.format(e.strerror))
except StopIteration:
    print('StopIteration reached')
finally:
    print('{0} -- {1}'.format(fname, lnumber))
    print('Odd lines => {0}'.format(':'.join(odd)))
    close()

Running it like:

python3 script.py file[123]

Both scripts yield same result:

one
two
three
file1 -- 3
Odd lines => one:three
monday
tuesday
wednesday
thursday
file2 -- 4
Odd lines => monday:wednesday
red
green
blue
file3 -- 3
Odd lines => red:blue

It does what I want but not the way I want. None of StopIteration, EOFError or a check on an empty line detect last one. And the use of additional variables and fileinput.filelineno() to do post-processing of previous file seems weird for me, at least compared with perl. Did I miss something? How would you solve this kind of problem in a better way?

4

1 回答 1

2

就像是:

import fileinput
from itertools import islice

for filename in list_of_filenames:
    fin = fileinput.input(filename)
    odd = [line.strip() for line in islice(fin, None, None, 2)]
    # We'll be at EOF at this point...
    print(fin.lineno(), odd)
于 2013-08-14T11:23:38.287 回答