473,385 Members | 2,004 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Using re to get data from text file

I'm a Python newbie and I'm having trouble with Regular Expressions when
reading in a text file. Here is a sample layout of the input file:

09/04/2004 Virginia 44 Temple 14
09/04/2004 LSU 22 Oregon State 21
09/09/2004 Troy State 24 Missouri 14

As you can see, the text file contains a list of games. Each game has a
date, a winning team, the winning team's score, the losing team, and the
losing team's score. If I set up my program to import the data with fixed
length format's its no problem. But some of my text files have different
layouts. For instance, some only have one space between a team name and
their score.

Here's how I read in the file using fixed length fields:

filename = sys.argv[1]
file = open (filename, 'r')

schedule = [] # make a list called schedule

while True:
line = file.readline()
if not line: break
game = {} # make a dictionary called game
game['date'] = line[0:10] # fixed length field
game['team1'] = string.strip (line[12:40])
game['score1'] = line[40:42]
game['team2'] = string.strip (line[44:72])
game['score2'] = line[72:74]
schedule.append(game)

file.close()

Note: I'm stripping whitespace from the team names because I don't want
the team name to actually be a fixed length.

How would I set this up to read in the data using Regular expressions?

I've tried this:

while True:
line = file.readline ()
if not line: break
game = {}
datePattern = re.compile('^(\d{2})\D+(\d{2})\D+(\d{4})')

Here's where I get stuck. What do I do from here? I just don't know how
to import the text and assign it to the proper fields using the re module.

Jul 18 '05 #1
6 2637
Jocknerd <jo*******@yahoo.com> wrote:
I'm a Python newbie and I'm having trouble with Regular Expressions when
reading in a text file. Here is a sample layout of the input file:

09/04/2004 Virginia 44 Temple 14
09/04/2004 LSU 22 Oregon State 21
09/09/2004 Troy State 24 Missouri 14

As you can see, the text file contains a list of games. Each game has a
date, a winning team, the winning team's score, the losing team, and the
losing team's score. If I set up my program to import the data with fixed
length format's its no problem. But some of my text files have different
layouts. For instance, some only have one space between a team name and
their score.

Here's how I read in the file using fixed length fields:

filename = sys.argv[1]
file = open (filename, 'r')

schedule = [] # make a list called schedule

while True:
line = file.readline()
if not line: break
game = {} # make a dictionary called game
game['date'] = line[0:10] # fixed length field
game['team1'] = string.strip (line[12:40])
game['score1'] = line[40:42]
game['team2'] = string.strip (line[44:72])
game['score2'] = line[72:74]
schedule.append(game)

file.close()

Note: I'm stripping whitespace from the team names because I don't want
the team name to actually be a fixed length.

How would I set this up to read in the data using Regular expressions?

I've tried this:

while True:
line = file.readline ()
if not line: break
game = {}
datePattern = re.compile('^(\d{2})\D+(\d{2})\D+(\d{4})')

Here's where I get stuck. What do I do from here? I just don't know how
to import the text and assign it to the proper fields using the re module.

Your format is a bit complicated since team's name can be variable
words. But, I'm assuming that they don't have any digit as part of
their name. So, use '\d+' to separate the fields. Eg.
re.split ('\d+', line)
re.split ('(\d+)', line)
re.split ('(\d+)', line[10:])

--
William Park <op**********@yahoo.ca>
Open Geometry Consulting, Toronto, Canada
Jul 18 '05 #2
Jocknerd wrote:
How would I set this up to read in the data using Regular expressions?

I've tried this:

while True:
line = file.readline ()
if not line: break
game = {}
datePattern = re.compile('^(\d{2})\D+(\d{2})\D+(\d{4})')


Regular expressions are tricky. Luckily, there are plenty
of resources available to learn. Here's a suggestion for how
to read your data.

The subtle parts are:
- I'm using re.X so I can document each of the fields in the re
- The team name must only contain letters
[a-zA-Z]+ means "set of letters" (that is, a word)
[a-zA-Z]+(\s[a-zA-Z]+)* means "one or more words separated
by spaces

I also use the ^ and $ symbols to make sure the match is
complete across the whole line.

If you have teams with digits in the name (eg, "49ers") then
you'll have to change the definition of 'word' appropriately.
I made it a strict test to ensure sure there wasn't an accidental
confusion with a score.
import re

pat = re.compile("""
^\s* # allow spaces at the start
(\d\d)/(\d\d)/(\d\d\d\d) # the month, day, and year

\s+ # spaces to the first team name
([a-zA-Z]+(\s+[a-zA-Z]+)*) # one or more words separated by spaces
\s+ # spaces to the first score
(\d+) # the score

\s+ # spaces to the second team name
([a-zA-Z]+(\s+[a-zA-Z]+)*) # one or more words separated by spaces
\s+ # spaces to the second score
(\d+) # the score

\s*$ # allow spaces, up to the end
""", re.X)
tests = [
"09/04/2004 Virginia 44 Temple 14",
"09/04/2004 LSU 22 Oregon State 21",
"09/09/2004 Troy State 24 Missouri 14",
"01/02/2003 Florida State 103 University of Miami 2",
]

for test in tests:
m = pat.match(test)
if not m:
raise AssertionError("test failure")
print "Match results:"
print " month", m.group(1), "day", m.group(2), "year", m.group(3)
print " team #1", m.group(4), "score", m.group(6)
print " team #2", m.group(7), "score", m.group(9)
Here's the output

Match results:
month 09 day 04 year 2004
team #1 Virginia score 44
team #2 Temple score 14
Match results:
month 09 day 04 year 2004
team #1 LSU score 22
team #2 Oregon State score 21
Match results:
month 09 day 09 year 2004
team #1 Troy State score 24
team #2 Missouri score 14
Match results:
month 01 day 02 year 2003
team #1 Florida State score 103
team #2 University of Miami score 2
Andrew
da***@dalkescientific.com
Jul 18 '05 #3
On Fri, Sep 10, 2004 at 10:29:27AM -0400, Jocknerd wrote:
I'm a Python newbie and I'm having trouble with Regular Expressions when
reading in a text file. Here is a sample layout of the input file:

09/04/2004 Virginia 44 Temple 14
09/04/2004 LSU 22 Oregon State 21
09/09/2004 Troy State 24 Missouri 14

As you can see, the text file contains a list of games. Each game has a
date, a winning team, the winning team's score, the losing team, and the
losing team's score. If I set up my program to import the data with fixed
length format's its no problem. But some of my text files have different
layouts. For instance, some only have one space between a team name and
their score.

[...]

I've tried this:

while True:
line = file.readline ()
if not line: break
game = {}
datePattern = re.compile('^(\d{2})\D+(\d{2})\D+(\d{4})')

Here's where I get stuck. What do I do from here? I just don't know how
to import the text and assign it to the proper fields using the re module.


how about this:

import re, time, datetime

class Game(object):
def __init__(self, d, t1, t2, s1, s2):
self.date = d
self.team1 = t1
self.team2 = t2
self.score1 = s1
self.score2 = s2

def __str__(self):
return 'On %s, %s beat %s %s-%s' % (self.date,
self.team1,
self.team2,
self.score1,
self.score2)

class Games(Game):
_re = re.compile(r'([\d/]+)'
+ r'\s+(\w[\w\s]+\w)\s+(\d+)' * 2
+ r'\s*$')
def __init__(self, filename):
self.games = []
for line in file('games.csv'):
match = re.search(self._re, line)
if match:
d, t1, s1, t2, s2 = match.groups()
d = time.strptime(d, '%m/%d/%Y') # m/d/Y! yecch!
d = datetime.date(*d[:3])
self.games.append(Game(d, t1, t2, s1, s2))

if __name__ == '__main__':
import sys
for i in Games(sys.argv[1]).games:
print i

woops! looks like I got carried away.

--
John Lenton (jo**@grulic.org.ar) -- Random fortune:
Of course you have a purpose -- to find a purpose.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)

iD8DBQFBQeivgPqu395ykGsRAg0uAKDAP3fRvwQk/kKcD4c4rlFqYI3OiwCfe80m
JQE5RMAU/oIQvIF6Zd/PshA=
=58wF
-----END PGP SIGNATURE-----

Jul 18 '05 #4
On Fri, 10 Sep 2004 14:53:32 +0000, William Park wrote:
Jocknerd <jo*******@yahoo.com> wrote:
I'm a Python newbie and I'm having trouble with Regular Expressions when
reading in a text file. Here is a sample layout of the input file:

09/04/2004 Virginia 44 Temple 14
09/04/2004 LSU 22 Oregon State 21
09/09/2004 Troy State 24 Missouri 14

As you can see, the text file contains a list of games. Each game has a
date, a winning team, the winning team's score, the losing team, and the
losing team's score. If I set up my program to import the data with fixed
length format's its no problem. But some of my text files have different
layouts. For instance, some only have one space between a team name and
their score.

Here's how I read in the file using fixed length fields:

filename = sys.argv[1]
file = open (filename, 'r')

schedule = [] # make a list called schedule

while True:
line = file.readline()
if not line: break
game = {} # make a dictionary called game
game['date'] = line[0:10] # fixed length field
game['team1'] = string.strip (line[12:40])
game['score1'] = line[40:42]
game['team2'] = string.strip (line[44:72])
game['score2'] = line[72:74]
schedule.append(game)

file.close()

Note: I'm stripping whitespace from the team names because I don't want
the team name to actually be a fixed length.

How would I set this up to read in the data using Regular expressions?

I've tried this:

while True:
line = file.readline ()
if not line: break
game = {}
datePattern = re.compile('^(\d{2})\D+(\d{2})\D+(\d{4})')

Here's where I get stuck. What do I do from here? I just don't know how
to import the text and assign it to the proper fields using the re module.

Your format is a bit complicated since team's name can be variable
words. But, I'm assuming that they don't have any digit as part of
their name. So, use '\d+' to separate the fields. Eg.
re.split ('\d+', line)
re.split ('(\d+)', line)
re.split ('(\d+)', line[10:])


Couldn't figure out re.split. Didn't seem to do what I wanted. Here's
what did work:

#!/usr/bin/python

import re
filename = sys.argv[1]
file = open (filename, 'r')

schedule = []

pattern = re.compile(r'^(.*\D\d+\D\d+)\D(.*)\D(.*\d+)\D(.*)\ D(.*\d+)(.*)$')
while True:
line = file.readline()
if not line: break
g = {}
g['date'], g['team1'], g['score1'], g['team2'],
g['score2'],g['location'] = pattern.search(line).groups()
schedule.append(g)
file.close()

for game in schedule:
print game['date'], game['team1'], game['score1'], game['team2'],
game['score2']
Jul 18 '05 #5
Jocknerd <jo*******@yahoo.com> wrote:
09/04/2004 Virginia 44 Temple 14
09/04/2004 LSU 22 Oregon State 21
09/09/2004 Troy State 24 Missouri 14
Your format is a bit complicated since team's name can be variable
words. But, I'm assuming that they don't have any digit as part of
their name. So, use '\d+' to separate the fields. Eg.
re.split ('\d+', line)
re.split ('(\d+)', line)
re.split ('(\d+)', line[10:])


Couldn't figure out re.split. Didn't seem to do what I wanted. Here's
what did work:

#!/usr/bin/python

import re
filename = sys.argv[1]
file = open (filename, 'r')

schedule = []

pattern = re.compile(r'^(.*\D\d+\D\d+)\D(.*)\D(.*\d+)\D(.*)\ D(.*\d+)(.*)$')
while True:
line = file.readline()
if not line: break
g = {}
g['date'], g['team1'], g['score1'], g['team2'],
g['score2'],g['location'] = pattern.search(line).groups()
schedule.append(g)
file.close()

for game in schedule:
print game['date'], game['team1'], game['score1'], game['team2'],
game['score2']

In Bash shell, this kind of cut/slicing is a bit easier.

1. line='09/09/2004 Troy State 24 Missouri 14'
sscanf "$line" '%s %[^0-9] %[0-9] %[^0-9] %[0-9]' date team1 score1 team2 score2
declare -p date team1 score1 team2 score2

2. line='09/09/2004 Troy State 24 Missouri 14'
match "$line" '([0-9/]*) ([^0-9]*) ([0-9]*) ([^0-9]*) ([0-9]*)' a
date=a[1]
team1=a[2] score1=a[3]
team2=a[4] score2=a[5]
declare -p date team1 score1 team2 score2

Ref:
http://freshmeat.net/projects/bashdiff/
http://home.eol.ca/~parkw/index.html#bash
help sscanf
help match

--
William Park <op**********@yahoo.ca>
Open Geometry Consulting, Toronto, Canada
Jul 18 '05 #6
Jocknerd wrote:
pattern = re.compile(r'^(.*\D\d+\D\d+)\D(.*)\D(.*\d+)\D(.*)\ D(.*\d+)(.*)$')


Though I think that's esthetically poor. The .* groups
will cause a lot of backtracking.

Andrew
da***@dalkescientific.com

Jul 18 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Gregory A Greenman | last post by:
I'm trying to write a program in vb.net to automate filling out a series of forms on a website. There are three forms I need to fill out in sequence. The first one is urlencoded. My program is...
2
by: Roland Hall | last post by:
I have two(2) issues. I'm experiencing a little difficulty and having to resort to a work around. I already found one bug, although stated the bug was only in ODBC, which I'm not using. It...
3
by: Random Person | last post by:
Does anyone know how to use VBA to relink tables between two MS Access databases? We have two databases, one with VBA code and the other with data tables. The tables are referenced by linked...
11
by: Grasshopper | last post by:
Hi, I am automating Access reports to PDF using PDF Writer 6.0. I've created a DTS package to run the reports and schedule a job to run this DTS package. If I PC Anywhere into the server on...
0
by: Lokkju | last post by:
I am pretty much lost here - I am trying to create a managed c++ wrapper for this dll, so that I can use it from c#/vb.net, however, it does not conform to any standard style of coding I have seen....
7
by: Mark Waser | last post by:
Hi all, I'm trying to post multipart/form-data to a web page but seem to have run into a wall. I'm familiar with RFC 1867 and have done this before (with AOLServer and Tcl) but just can't seem...
21
KevinADC
by: KevinADC | last post by:
Note: You may skip to the end of the article if all you want is the perl code. Introduction Uploading files from a local computer to a remote web server has many useful purposes, the most...
24
by: allpervasive | last post by:
hi all, this is reddy, a beginner to c lang,,here i have some problems in reading and modifying the contents of a file,, hope you can help to solve this problem. Here i attach the file to be...
1
by: WeCi2i | last post by:
Okay, I have a problem that has been stumping me for weeks. I have tried many different solutions and this is pretty much my last resort. I have seen a lot of good answers give here so I figured I...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.