Tôi đang cố gắng sử dụng pyparsing để phân tích các cặp khóa-giá trị từ các nhận xét trong tài liệu. Một khóa bắt đầu ở đầu hàng, theo sau là một giá trị. Các giá trị có thể tiếp tục trên nhiều dòng bắt đầu bằng dấu cách.
nhập pyparsing dưới dạng pp
chuỗi = """
-- Đây là (a) #%^& bình luận
/*
tên1:val
name2: val2 với $*@) rác
name3: val3: with @)(*% multi-
dòng: nội dung
*/
"""
comment1 = pp.Literal("--") + pp.origenTextFor(pp.SkipTo(pp.LineEnd())).setDebug()
mã định danh = pp.Word(pp.alphanums + "_").setDebug()
meta1 = pp.LineStart() + mã định danh + pp.Literal( John) + pp.SkipTo(pp.LineEnd())
meta2 = pp.LineStart() + pp.White() + pp.SkipTo(pp.LineEnd())
metaval = meta1 + pp.ZeroOrMore(meta2)
metalist = pp.ZeroOrMore(comment1) + pp.Literal("/*") + pp.OneOrMore(metaval) + pp.Literal("*/")
if __name__ == "__main__":
p = metalist.parseString(chuỗi)
in(p)
thất bại:
Đã khớp {Empty SkipTo:(LineEnd) Empty} -> ['Đây là (a) #%^& nhận xét']
Tệp "C:\Users\user\py3\lib\site-packages\pyparsing.py", dòng 2305, trong ParseImpl
tăng ParseException(instring, loc, self.errmsg, self)
pyparsing.ParseException: Dự kiến bắt đầu dòng (tại char 32), (line:4, col:1)
vấn đề khớp khoảng trắng pyparsing Câu trả lời nói
LineStart luôn khó làm việc, nhưng ...
Nếu trình phân tích cú pháp ở hàng 4, cột 1 (cặp khóa-giá trị đầu tiên), tại sao nó không thể tìm thấy phần đầu của hàng? Cú pháp pyparsing chính xác để xác định các dòng bắt đầu bằng không có khoảng trắng và các dòng bắt đầu bằng khoảng trắng là gì?
Tôi nghĩ tôi đúng DòngBắt đầu
Sự nhầm lẫn là đối với DòngCuối
, Tôi có thể tìm kiếm một '\N'
nhân vật nhưngDòngBắt đầu
Không có ký tự riêng biệt. Vì vậy, trong DòngBắt đầu
, tôi kiểm tra xem vị trí của trình phân tích cú pháp hiện tại có chính xác ở vị trí không '\N'
sau; hoặc, nếu hiện tạihiện hữu '\N'
, vui lòng vượt qua nó và tiếp tục. Thật không may, tôi đã triển khai điều này ở một nơi làm xáo trộn vị trí báo cáo, do đó bạn gặp phải những lỗi kỳ lạ như "Không thể tìm thấy đầu hàng tại cột Phần đầu của một dòng khớp thành công. Ngoài ra, tôi nghĩ rằng tôi cần phải xem lại việc bỏ qua dòng mới ngầm này, hoặc vì vấn đề đó,DòngBắt đầu
Tất cả các khoảng trống đều bị bỏ qua.
Bây giờ, tôi đã làm cho mã của bạn hoạt động bằng cách mở rộng một chút biểu thức bắt đầu dòng của bạn như:
LS = pp.Optional(pp.LineEnd()) + pp.LineStart()
Và thay thế các tham chiếu LineStart trong meta1 và meta2 bằng LS:
comment1 = pp.Literal("--") + pp.origenTextFor(pp.SkipTo(pp.LineEnd())).setDebug()
mã định danh = pp.Word(pp.alphanums + "_").setDebug()
meta1 = LS + mã định danh + pp.Literal(+) + pp.SkipTo(pp.LineEnd())
meta2 = LS + pp.White() + pp.SkipTo(pp.LineEnd())
metaval = meta1 + pp.ZeroOrMore(meta2)
metalist = pp.ZeroOrMore(comment1) + pp.Literal("/*") + pp.OneOrMore(metaval) + pp.Literal("*/")
nếu như DòngBắt đầu
Nếu tình huống này khiến bạn không thoải mái, bạn có thể thử một chiến lược khác: sử dụng điều kiện thời gian phân tích cú pháp chỉ chấp nhận các mã định danh bắt đầu từ cột 1:
comment1 = pp.Literal("--") + pp.origenTextFor(pp.SkipTo(pp.LineEnd())).setDebug()
mã định danh = pp.Word(pp.alphanums + "_").setName("định danh")
định danh.addCondition(lambda instring,loc,toks: pp.col(loc,instring) == 1)
meta1 = mã định danh + pp.Literal( John) + pp.SkipTo(pp.LineEnd()).setDebug()
meta2 = pp.White().setDebug() + pp.SkipTo(pp.LineEnd()).setDebug()
metaval = meta1 + pp.ZeroOrMore(meta2, stopOn=pp.Literal('*/'))
metalist = pp.ZeroOrMore(comment1) + pp.Literal("/*") + pp.LineEnd() + pp.OneOrMore(metaval) + pp.Literal("*/")
Mã này hủy bỏ hoàn toàn DòngBắt đầu
, trong khi tôi tìm ra điều tôi muốn thẻ cụ thể này thực hiện. Tôi vẫn phải sửa đổi sự thay đổi
TRONG ZeroHoặcThêm
Lặp lại như thế này */
Nó sẽ không bị vô tình xử lý như nội dung bình luận liên tục.
Cảm ơn sự kiên nhẫn của bạn về vấn đề này - Tôi không muốn tung ra bản vá quá nhanh DòngBắt đầu
những thay đổi và sau đó phát hiện ra rằng tôi đã bỏ qua khả năng tương thích khác hoặc các trường hợp đặc biệt khác khiến tôi trở lại trạng thái hiện tại của lớp vốn không ở trạng thái tốt. Nhưng tôi sẽ cố gắng làm rõ hành vi này trước khi phát hành phiên bản 2.1.10.
Tôi là một lập trình viên xuất sắc, rất giỏi!