[英]Finding lists of elements within a string using Pyparsing
我正在嘗試使用 Pyparsing 解決以下問題:我想在字符串中搜索三種元素的出現:
示例字符串可以是“foo bar OBJ baz foo,bar
我想在自己的解析操作中處理這些元素中的每一個。
這是我的代碼:
import pyparsing
from pyparsing import Word, Literal, alphas
def found_word(s, l, t):
print('word')
def found_obj(s, l, t):
print('obj')
def found_list(s, l, t):
print('list')
def process(string):
word = ~Literal('OBJ ') + Word(alphas.lower())
word.setParseAction(lambda s,l,t: found_word(s, l, t))
obj = Literal('OBJ ') + Word(alphas.lower())
obj.setParseAction(lambda s,l,t: found_obj(s, l, t))
item = word | obj
list = pyparsing.delimitedList(item, delim=',')
list.setParseAction(lambda s,l,t: found_list(s, l, t))
element = word | obj | list
parser = pyparsing.OneOrMore(element)
parser.searchString(string).pprint()
if __name__ == "__main__":
process('foo bar OBJ baz foo,bar')
編輯:我在 parseActions 中進行了一些測試 output 只是為了查看它們是否被調用。 所需的 output 將是:
word
word
obj
word
word
list
實際的 output 是:
word
word
obj
word
word
即不調用列表的 parseAction。 為了實現這一點,我需要如何更改我的代碼?
更新delimitedList 沒有按我的預期工作。 當我打電話時
pyparsing.OneOrMore(list).searchString('foo,bar baz')
found_list
似乎被調用了兩次,盡管我的字符串中只有一個列表元素:
word
word
list
word
list
嘗試這個:
s = 'foo bar OBJ baz foo,bar'
for w in s.split(' '):
if w.islower():
print("word")
if 'OBJ' in w:
print("obj")
if ',' in w:
print('list')
您的list
沒有被解析的原因在於這個表達式:
element = word | obj | list
因為您正在檢查list
之前的word
(在 Python 中工作時,這是一個非常糟糕的變量名,順便說一句),所以“foo,bar”中的前導“foo”被作為一個word
處理,因為 '|' 是一個急切的運算符,匹配第一個匹配表達式。
您可以通過更改element
中表達式的順序來解決此問題:
element = list | word | obj
或者使用 '^' 而不是 '|'。 '^' 是一個耐心的運算符 - 它評估所有替代表達式並選擇最長的匹配項。
element = word ^ obj ^ list
通過這些更改中的任何一個,您的 output 現在變為:
word
list
word
list
obj
word
word
list
為什么所有列表都匹配? 因為delimitedList
將匹配單個項目:
>>> wd = Word(alphas)
>>> wdlist = delimitedList(wd)
>>> print(wdlist.parseString('xyz'))
['xyz']
如果要強制列表必須具有 > 1 項,則可以添加條件解析操作:
>>> wdlist.addCondition(lambda t: len(t)>1)
>>> print(wdlist.parseString('xyz'))
... raises exception ...
此外,delimitedLists 不會自動對它們的結果進行分組:
>>> print((wd + wdlist).parseString('xyz abc,def'))
['xyz', 'abc', 'def']
如果要將列表內容作為列表保留在結果中,則將列表表達式包裝在一個組中:
>>> print((wd + Group(wdlist)).parseString('xyz abc,def'))
['xyz', ['abc', 'def']]
這是我的process()
方法的更新版本:
def process(string):
print(string)
word = ~Literal('OBJ') + Word(alphas.lower())
word.addParseAction(lambda s,l,t: found_word(s, l, t))
word.setName("word")
obj = Literal('OBJ') + Word(alphas.lower())
obj.setName("obj")
obj.addParseAction(lambda s,l,t: found_obj(s, l, t))
item = word | obj
list = Group(pyparsing.delimitedList(item, delim=',')
.addCondition(lambda t: len(t)>1))
list.setName("list")
list.addParseAction(lambda s,l,t: found_list(s, l, t))
element = obj | list | word
parser = pyparsing.OneOrMore(element)
parser.searchString(string).pprint()
這給出了這個 output:
foo bar OBJ baz foo,bar
word
word
word
word
obj
word
word
list
[['foo', 'bar', 'OBJ', 'baz', ['foo', 'bar']]]
您會注意到我為您的每個表達式添加了setName()
調用。 這樣我就可以添加setDebug()
來獲取 pyparsing 的調試 output。 通過添加:
word.setDebug()
obj.setDebug()
list.setDebug()
在調用parseString
之前,你會得到這個調試 output。 它可能有助於解釋為什么您在示例 output 中獲得了重復的“單詞”。
foo bar OBJ baz foo,bar
Match obj at loc 0(1,1)
Exception raised:Expected "OBJ", found 'f' (at char 0), (line:1, col:1)
Match list at loc 0(1,1)
Match word at loc 0(1,1)
word
Matched word -> ['foo']
Exception raised:failed user-defined condition, found 'f' (at char 0), (line:1, col:1)
Match word at loc 0(1,1)
word
Matched word -> ['foo']
Match obj at loc 3(1,4)
Exception raised:Expected "OBJ", found 'b' (at char 4), (line:1, col:5)
Match list at loc 3(1,4)
Match word at loc 4(1,5)
word
Matched word -> ['bar']
Exception raised:failed user-defined condition, found 'b' (at char 4), (line:1, col:5)
Match word at loc 3(1,4)
word
Matched word -> ['bar']
Match obj at loc 7(1,8)
obj
Matched obj -> ['OBJ', 'baz']
Match obj at loc 15(1,16)
Exception raised:Expected "OBJ", found 'f' (at char 16), (line:1, col:17)
Match list at loc 15(1,16)
Match word at loc 16(1,17)
word
Matched word -> ['foo']
Match word at loc 20(1,21)
word
Matched word -> ['bar']
list
Matched list -> [['foo', 'bar']]
Match obj at loc 23(1,24)
Exception raised:Expected "OBJ", found end of text (at char 23), (line:1, col:24)
Match list at loc 23(1,24)
Match word at loc 23(1,24)
Exception raised:Expected W:(abcd...), found end of text (at char 23), (line:1, col:24)
Match obj at loc 23(1,24)
Exception raised:Expected "OBJ", found end of text (at char 23), (line:1, col:24)
Exception raised:Expected {word | obj}, found end of text (at char 23), (line:1, col:24)
Match word at loc 23(1,24)
Exception raised:Expected W:(abcd...), found end of text (at char 23), (line:1, col:24)
Match obj at loc 23(1,24)
Exception raised:Expected "OBJ", found end of text (at char 23), (line:1, col:24)
Match list at loc 23(1,24)
Match word at loc 23(1,24)
Exception raised:Expected W:(abcd...), found end of text (at char 23), (line:1, col:24)
Match obj at loc 23(1,24)
Exception raised:Expected "OBJ", found end of text (at char 23), (line:1, col:24)
Exception raised:Expected {word | obj}, found end of text (at char 23), (line:1, col:24)
Match word at loc 23(1,24)
Exception raised:Expected W:(abcd...), found end of text (at char 23), (line:1, col:24)
[['foo', 'bar', 'OBJ', 'baz', ['foo', 'bar']]]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.