我試圖解析可以使用pyparsing用反斜槓 - 換行符組合(「\\n
」)拆分多行的單詞。下面是我做了什麼:使用pyparsing來解析一個單詞escape-split在多行
from pyparsing import *
continued_ending = Literal('\\') + lineEnd
word = Word(alphas)
split_word = word + Suppress(continued_ending)
multi_line_word = Forward()
multi_line_word << (word | (split_word + multi_line_word))
print multi_line_word.parseString(
'''super\\
cali\\
fragi\\
listic''')
我得到的輸出是['super']
,而預期輸出爲['super', 'cali', fragi', 'listic']
。更妙的是所有的人都加入了一個單詞(我認爲我可以做multi_line_word.parseAction(lambda t: ''.join(t))
。
我試着在pyparsing helper看着這個代碼,但它給了我一個錯誤,maximum recursion depth exceeded
。
編輯2009-11-15:我意識到晚些時候pyparsing變得有點慷慨的問候空白,並導致一些可憐的假設,我以爲我是爲解析了很多寬鬆也就是說,我們要看到的任何字,逸出的部分之間和EOL字符沒有空白。
我意識到上面的小字符串作爲測試用例是不夠的,所以我寫了下面的單元測試。可以通過這些測試應該能夠匹配什麼,我直覺地認爲,作爲一個逃生分割字—和僅逃生分割字碼。他們不會匹配一個基本單詞,而不是逃避分裂。我們可以—,我相信應該—使用不同的語法結構。這使得它們兩個完全整齊。
import unittest
import pyparsing
# Assumes you named your module 'multiline.py'
import multiline
class MultiLineTests(unittest.TestCase):
def test_continued_ending(self):
case = '\\\n'
expected = ['\\', '\n']
result = multiline.continued_ending.parseString(case).asList()
self.assertEqual(result, expected)
def test_continued_ending_space_between_parse_error(self):
case = '\\ \n'
self.assertRaises(
pyparsing.ParseException,
multiline.continued_ending.parseString,
case
)
def test_split_word(self):
cases = ('shiny\\', 'shiny\\\n', ' shiny\\')
expected = ['shiny']
for case in cases:
result = multiline.split_word.parseString(case).asList()
self.assertEqual(result, expected)
def test_split_word_no_escape_parse_error(self):
case = 'shiny'
self.assertRaises(
pyparsing.ParseException,
multiline.split_word.parseString,
case
)
def test_split_word_space_parse_error(self):
cases = ('shiny \\', 'shiny\r\\', 'shiny\t\\', 'shiny\\ ')
for case in cases:
self.assertRaises(
pyparsing.ParseException,
multiline.split_word.parseString,
case
)
def test_multi_line_word(self):
cases = (
'shiny\\',
'shi\\\nny',
'sh\\\ni\\\nny\\\n',
' shi\\\nny\\',
'shi\\\nny '
'shi\\\nny captain'
)
expected = ['shiny']
for case in cases:
result = multiline.multi_line_word.parseString(case).asList()
self.assertEqual(result, expected)
def test_multi_line_word_spaces_parse_error(self):
cases = (
'shi \\\nny',
'shi\\ \nny',
'sh\\\n iny',
'shi\\\n\tny',
)
for case in cases:
self.assertRaises(
pyparsing.ParseException,
multiline.multi_line_word.parseString,
case
)
if __name__ == '__main__':
unittest.main()
使用'Combine'也不會強制介入空格。 – PaulMcG 2009-11-16 06:24:46
有趣。嘗試過 'multi_line_word = Combine(Combine(OneOrMore(split_word))+ Optional(word))' 但是它在'sh \\\ n iny''情況下破壞了,因爲它不會引發異常,而是返回'['sh']'。我錯過了什麼嗎? – gotgenes 2009-11-16 20:04:49
那麼,你的話不僅僅是字母跨越一個'\' - 換行符,但在字母'i'之前那裏有空格,這被視爲分詞符號,所以Combine在'sh'後面停下來。你*可以*修改與相鄰的= False構造函數參數的組合,但要注意 - 你可能最終將整個文件作爲一個單詞吸引!或者,您可以重新定義您的continue_ending的定義,以便在lineEnd後包含任何空格,如果您還想摺疊任何前導空格。 – PaulMcG 2009-11-17 01:56:25