By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,358 Members | 2,957 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,358 IT Pros & Developers. It's quick & easy.

Parsing a search string

P: n/a
Happy new year! Since I have run out of alcohol, I'll ask a question that I
haven't really worked out an answer for yet. Is there an elegant way to turn
something like:
moo cow "farmer john" -zug


into:

['moo', 'cow', 'farmer john'], ['zug']

I'm trying to parse a search string so I can use it for SQL WHERE constraints,
preferably without horrifying regular expressions. Uhh yeah.

From 2005,
Freddie

Jul 18 '05 #1
Share this Question
Share on Google+
15 Replies


P: n/a
How ,
I just posted on something similar earlier ;)
Ok first of all you might want to try shlex it is in the standard
library.
If you don't know what cStringIO is dont worry about it it is just to
give a file like object to pass to shlex.
If you have a file just pass it in opened.
example: a = shlex.shlex(open('mytxt.txt','r'))

py>import cStringIO
py>d = cStringIO.StringIO()
py>d.write('moo cow "farmer john" -zug')
py>d.seek(0)
py>a = shlex.shlex(d)
py>a.get_token()
'moo'
py>a.get_token()
'cow'
py>a.get_token()
'"farmer john"'
py>a.get_token()
'-'
py>a.get_token()
'zug'
py>a.get_token()
''
# ok we try again this time we add - to valid chars so we can get it
grouped as a single token .
py>d.seek(0)
py>a = shlex.shlex(d)
py>a.wordchars += '-' # add the hyphen
py>a.get_token()
'moo'
py>a.get_token()
'cow'
py>a.get_token()
'"farmer john"'
py>a.get_token()
'-zug'
py>a.get_token()
''

Hth,
M.E.Farmer

Jul 18 '05 #2

P: n/a
That's not bad going considering you've only run out of alcohol at 6 in
the morning and *then* ask python questions.

Anyway - you could write a charcter-by-character parser function that
would do that in a few minutes...

My 'listquote' module has one - but it splits on commas not whitespace.
Sounds like you're looking for a one-liner though.... regular
expressions *could* do it...............

Regards,

Fuzzy
http://www.voidspace.org.uk/atlantib...tml#llistquote

Jul 18 '05 #3

P: n/a
Freddie wrote:
Happy new year! Since I have run out of alcohol, I'll ask a question that I
haven't really worked out an answer for yet. Is there an elegant way to turn
something like:
> moo cow "farmer john" -zug


into:

['moo', 'cow', 'farmer john'], ['zug']

I'm trying to parse a search string so I can use it for SQL WHERE constraints,
preferably without horrifying regular expressions. Uhh yeah.


The shlex approach, finished:

searchstring = 'moo cow "farmer john" -zug'
lexer = shlex.shlex(searchstring)
lexer.wordchars += '-'
poslist, neglist = [], []
while 1:
token = lexer.get_token()
# token is '' on eof
if not token: break
# remove quotes
if token[0] in '"\'':
token = token[1:-1]
# select in which list to put it
if token[0] == '-':
neglist.append(token[1:])
else:
poslist.append(token)

regards,
Reinhold
Jul 18 '05 #4

P: n/a
As I noted before shlex requires a file like object or a open file .
py> import shlex
py> a = shlex.shlex('fgfgfg dgfgfdgfdg')
py> a.get_token()
Traceback (most recent call last):
File "<input>", line 1, in ?
File ".\shlex.py", line 74, in get_token
raw = self.read_token()
File ".\shlex.py", line 100, in read_token
nextchar = self.instream.read(1)
AttributeError: 'str' object has no attribute 'read'

M.E.Farmer

Jul 18 '05 #5

P: n/a
M.E.Farmer wrote:
As I noted before shlex requires a file like object or a open file .
py> import shlex
py> a = shlex.shlex('fgfgfg dgfgfdgfdg')
py> a.get_token()
Traceback (most recent call last):
File "<input>", line 1, in ?
File ".\shlex.py", line 74, in get_token
raw = self.read_token()
File ".\shlex.py", line 100, in read_token
nextchar = self.instream.read(1)
AttributeError: 'str' object has no attribute 'read'


Which Python version are you using?

The docs say that since Py2.3 strings are accepted.

regards,
Reinhold
Jul 18 '05 #6

P: n/a
I am right in the middle of doing text parsing so I used your example as a
mental exercise. :-)

Here's a NDFA for your text:

b 0 1-9 a-Z , . + - ' " \n
S0: S0 E E S1 E E E S3 E S2 E
S1: T1 E E S1 E E E E E E T1
S2: S2 E E S2 E E E E E T2 E
S3: T3 E E S3 E E E E E E T3

and the end-states are:

E: error in text
T1: You have the words: moo, cow
T2: You get "farmer john" (w quotes)
T3: You get zug

Can't gurantee that I did it right - I did it really quick - and it's
*specific* to your text string.

Now just need to hire a programmer to write some clean Python parsing code.
:-)

--
It's me

"Freddie" <li**********@zebra-madcowdisease.giraffe-org> wrote in message
news:kX****************@text.usenetserver.com...
Happy new year! Since I have run out of alcohol, I'll ask a question that I haven't really worked out an answer for yet. Is there an elegant way to turn something like:
> moo cow "farmer john" -zug
into:

['moo', 'cow', 'farmer john'], ['zug']

I'm trying to parse a search string so I can use it for SQL WHERE

constraints, preferably without horrifying regular expressions. Uhh yeah.

From 2005,
Freddie


Jul 18 '05 #7

P: n/a
Ah! that is what the __future__ brings I guess.........
Damn that progress making me outdated ;)
Python 2.2.3 ( a lot of extensions I use are stuck there , so I still
use it)
M.E.Farmer

Jul 18 '05 #8

P: n/a
M.E.Farmer wrote:
Ah! that is what the __future__ brings I guess.........
Damn that progress making me outdated ;)
Python 2.2.3 ( a lot of extensions I use are stuck there , so I still
use it)


I'm also positively surprised how many cute little additions are there
every new Python version. Great thanks to the great devs!

Reinhold
Jul 18 '05 #9

P: n/a
"It's me" wrote:
Here's a NDFA for your text:

b 0 1-9 a-Z , . + - ' " \n
S0: S0 E E S1 E E E S3 E S2 E
S1: T1 E E S1 E E E E E E T1
S2: S2 E E S2 E E E E E T2 E
S3: T3 E E S3 E E E E E E T3


Now if I only had an NDFA for parsing that syntax...

:)
Andrew
da***@dalkescientific.com

Jul 18 '05 #10

P: n/a

"Andrew Dalke" <da***@dalkescientific.com> wrote in message
news:pa****************************@dalkescientifi c.com...
"It's me" wrote:
Here's a NDFA for your text:

b 0 1-9 a-Z , . + - ' " \n
S0: S0 E E S1 E E E S3 E S2 E
S1: T1 E E S1 E E E E E E T1
S2: S2 E E S2 E E E E E T2 E
S3: T3 E E S3 E E E E E E T3
Now if I only had an NDFA for parsing that syntax...


Just finished one (don't ask me to show it - very clumpsy Python code -
still in learning mode). :)

Here's one for parsing integer:

# b 0 1-9 , . + - ' " a-Z \n
# S0: S0 S0 S1 T0 E S2 S2 E E E T0
# S1: S3 S1 S1 T1 E E E E E E T1
# S2: E S2 S1 E E E E E E E E
# S3: S3 T2 T2 T1 T2 T2 T2 T2 T2 T2 T1

T0: you got a null token
T1: you got a good token, separator was ","
T2: you got a good token b, separator was " "
E: bad token

:)
Andrew
da***@dalkescientific.com

Jul 18 '05 #11

P: n/a
Freddie wrote:
I'm trying to parse a search string so I can use it for SQL WHERE
constraints, preferably without horrifying regular expressions. Uhh yeah.


If you're interested, I've written a function that parses query strings
using a customizable version of Google's search syntax.

Features include:
- Binary operators like OR
- Unary operators like '-' for exclusion
- Customizable modifiers like Google's site:, intitle:, inurl: syntax
- *No* query is an error (invalid characters are fixed up, etc.)
- Result is a dictionary in one of two possible forms, both geared
towards being input to an search method for your database

I'd be glad to post the code, although I'd probably want to have a last
look at it before I let others see it...

--
Brian Beck
Adventurer of the First Order
Jul 18 '05 #12

P: n/a
Andrew Dalke wrote:
"It's me" wrote:
Here's a NDFA for your text:

b 0 1-9 a-Z , . + - ' " \n
S0: S0 E E S1 E E E S3 E S2 E
S1: T1 E E S1 E E E E E E T1
S2: S2 E E S2 E E E E E T2 E
S3: T3 E E S3 E E E E E E T3


Now if I only had an NDFA for parsing that syntax...


Parsing your sentence as written ("if I only had"): If you were the
sole keeper of the secret??

Parsing it as intended ("if only I had"), and ignoring the smiley:
Looks like a fairly straight-forward state-transition table to me. The
column headings are not aligned properly in the message, b means blank,
a-Z is bletchworthy, but the da Vinci code it ain't.

If only we had an NDFA (whatever that is) for guessing what acronyms
mean ...

Where I come from:
DFA = deterministic finite-state automaton
NFA = non-det......
SFA = content-free
NFI = concept-free
NDFA = National Dairy Farmers' Association

HTH, and Happy New Year!

Jul 18 '05 #13

P: n/a

"John Machin" <sj******@lexicon.net> wrote in message
news:11**********************@c13g2000cwb.googlegr oups.com...
Andrew Dalke wrote:
"It's me" wrote:
Here's a NDFA for your text:

b 0 1-9 a-Z , . + - ' " \n
S0: S0 E E S1 E E E S3 E S2 E
S1: T1 E E S1 E E E E E E T1
S2: S2 E E S2 E E E E E T2 E
S3: T3 E E S3 E E E E E E T3
Now if I only had an NDFA for parsing that syntax...


Parsing your sentence as written ("if I only had"): If you were the
sole keeper of the secret??

Parsing it as intended ("if only I had"), and ignoring the smiley:
Looks like a fairly straight-forward state-transition table to me.


Exactly.
The
column headings are not aligned properly in the message, b means blank,
a-Z is bletchworthy, but the da Vinci code it ain't.

If only we had an NDFA (whatever that is) for guessing what acronyms
mean ...


I believe (I am not a computer science major):

NDFA = non-deterministic finite automata

and:

S: state
T: terminal
E: error

So, S1 means State #1..T1 means Terminal #1, so forth....

You are correct that parsing that table is not hard.

a) Set up a stack and place the buffer onto the stack, start with S0
b) For each character that comes from the stack, looking up the next state
for that token
c) If it's not a T or E state, jump to that state
d) If it's a T or E state, finish
Jul 18 '05 #14

P: n/a
Reinhold Birkenfeld wrote:
Freddie wrote:
Happy new year! Since I have run out of alcohol, I'll ask a question that I
haven't really worked out an answer for yet. Is there an elegant way to turn
something like:
> moo cow "farmer john" -zug


into:

['moo', 'cow', 'farmer john'], ['zug']

I'm trying to parse a search string so I can use it for SQL WHERE constraints,
preferably without horrifying regular expressions. Uhh yeah.

The shlex approach, finished:

searchstring = 'moo cow "farmer john" -zug'
lexer = shlex.shlex(searchstring)
lexer.wordchars += '-'
poslist, neglist = [], []
while 1:
token = lexer.get_token()
# token is '' on eof
if not token: break
# remove quotes
if token[0] in '"\'':
token = token[1:-1]
# select in which list to put it
if token[0] == '-':
neglist.append(token[1:])
else:
poslist.append(token)

regards,
Reinhold


Thanks for this, though there was one issue:
lexer = shlex.shlex('moo cow +"farmer john" -dog')
lexer.wordchars += '-+'
while 1: .... tok = lexer.get_token()
.... if not tok: break
.... print tok
....
moo
cow
+"farmer
john"
-dog

The '+"farmer john"' part would be turned into two seperate words, '+"farmer'
and 'john"'. I ended up using shlex.split() (which the docs say is new in
Python 2.3), which gives me the desired result. Thanks for the help from
yourself and M.E.Farmer :)

Freddie
shlex.split('moo cow +"farmer john" -"evil dog"') ['moo', 'cow', '+farmer john', '-evil dog'] shlex.split('moo cow +"farmer john" -"evil dog" +elephant')

['moo', 'cow', '+farmer john', '-evil dog', '+elephant']

Jul 18 '05 #15

P: n/a

py>b = shlex.shlex(a)
py>while 1:
.... tok = b.get_token()
.... if not tok: break
.... print tok
....
moo
cow
+
"farmer john"
-
dog

Just wanted to share this just in case it might be relevant .
It seems if we don't add +- to wordchars then we get a different split
on "farmer john".
M.E.Farmer

Jul 18 '05 #16

This discussion thread is closed

Replies have been disabled for this discussion.