Pyparsing: extrair comprimento variável, conteúdo variável, substring de espaço em branco variável
Eu preciso extrair os escores de Gleason de um arquivo plano de artigos diagnósticos finais de prostatectomia. Essas pontuações sempre têm a palavra Gleason e dois números que se somam a outro número. Os humanos digitaram isso em mais de duas décadas. Várias convenções de espaço em branco e modificadores estão incluídas. Abaixo está minha forma Backus-Naur até agora, e dois registros de exemplo. Apenas para prostatectomias, estamos olhando para mais de mil casos.
Eu estou usando pyparsing porque eu estou aprendendo python e não tenho boas lembranças da minha exposição muito limitada a escrita de regex.
Minha pergunta: como posso extrair essas notas de Gleason sem analisar cada outro dado opcional que pode ou não estar nesses diagnósticos finais?
num = Word(nums)
record ::= accessionDate + accessionNumber + patMedicalRecordNum + finalDxText
accessionDate ::= num + "/" + num + "/" num
accessionNumber ::= "S" + num + "-" + num
patMedicalRecordNum ::= num + "/" + num + "-" + num + "-" + num
finalDxText ::= listOfParts + optionalComment + optionalpTNMStage
listOfParts ::= OneOrMore(part)
part ::= <multiline idiosyncratic freetext which may contain a Gleason score I want> + optionalpTNMStage
optionalComment ::= <multiline idiosyncratic freetext which may contain a Gleason score I don't want>
optionalpTNMStage ::= <multiline idiosyncratic freetext which may contain a Gleason score I don't want>
01/01/11 S11-55555 20/444-55-6666 A. PROSTATE AND SEMINAL VESICLES, PROSTATECTOMY:
- ADENOCARCINOMA.
TOTAL GLEASON SCORE: GLEASON 5+4=9
TUMOR LOCATION: BILATERAL
TUMOR QUANTITATION: 15% OF PROSTATE INVOLVED BY TUMOR
EXTRAPROSTATIC EXTENSION: PRESENT AT RIGHT POSTERIOR
SEMINAL VESICLE INVASION: PRESENT
MARGINS: UNINVOLVED
LYMPHOVASCULAR INVASION: PRESENT
PERINEURAL INVASION: PRESENT
LYMPH NODES (SPECIMENS B AND C):
NUMBER EXAMINED: 25
NUMBER INVOLVED: 1
DIAMETER OF LARGEST METASTASIS: 1.7 mm
ADDITIONAL FINDINGS: HIGH-GRADE PROSTATIC INTRAEPITHELIAL NEOPLASIA,
ACUTE AND CHRONIC INFLAMMATION, INTRADUCTAL EXTENSION OF INVASIVE
CARCINOMA
PATHOLOGIC STAGE: pT3b N1 MX
B. LYMPH NODES, RIGHT PELVIC, EXCISION:
- ONE OF SEVENTEEN LYMPH NODES POSITIVE FOR METASTASIS (1/17).
C. LYMPH NODES, LEFT PELVIC, EXCISION:
- EIGHT LYMPH NODES NEGATIVE FOR METASTASIS (0/8).
01/02/11 S11-4444 20/111-22-3333 PROSTATE AND SEMINAL VESICLES, PROSTATECTOMY:
- ADENOCARCINOMA.
GLEASON SCORE: 3 + 3 = 6 WITH TERTIARY PATTERN OF 5.
TUMOR QUANTITATION: APPROXIMATELY 10% BY VOLUME.
TUMOR LOCATION: BILATERAL.
EXTRAPROSTATIC EXTENSION: NOT IDENTIFIED.
MARGINS: NEGATIVE.
PERINEURAL INVASION: IDENTIFIED.
LYMPH-VASCULAR INVASION: NOT IDENTIFIED.
SEMINAL VESICLE/VASA DEFERENTIA INVASION: NOT IDENTIFIED.
LYMPH NODES: NONE SUBMITTED.
OTHER: HIGH GRADE PROSTATIC INTRAEPITHELIAL NEOPLASIA.
PATHOLOGIC STAGE (pTNM): pT2c NX.
Divulgação completa: sou um médico fazendo pesquisa; Este é o meu primeiro trabalho real com python. Eu li o Python de Aprendizagem de Lutz, o Aprendizado de Pitão de Shaw, o Caminho Difícil, e trabalhei com vários conjuntos de problemas. Eu revisei várias perguntas relacionadas ao pyparsing neste fórum, o wiki pyparsing, e comprei e li o Getting Started with Pyparsing do Sr. McGuire. Talvez eu esteja fazendo uma pergunta quando realmente deveria ser dito que estou de pé em "A espiral da morte da frustração que é tão comum quando você tem que escrever parsers" (McGuire, 17)? Eu não sei. Até agora estou feliz por estar trabalhando no que pode realmente ser um projeto real.