超能力者指导一下新手,怎搞一个简单的文本解析器

Tips:点击图片进入下一页



最近零基础学了安德猴编程,准备自己做一个在线论文数据库查询app。

官方提供了api,用get方式获得查询内容,最后的内容可以两种形式呈现,一种ASN.1或者自设的Medline格式

ASN.1类似json,但是Google上找了一圈,没有简单入门的第三方类库,放弃
Medline直观,简单,但是要自己写个解析类


例如查询某个关键词,返回的是以下两条记录():

    PMID- 30213883 //ID是30213883
    OWN - NLM    // 所属是NLM
    STAT- Publisher //以此类推。。。。
    LR  - 20180914
    IS  - 1935-5548 (Electronic)
    IS  - 0149-5992 (Linking)
    DP  - 2018 Sep 13
    TI  - Estimated Resting Metabolic Rate and Body Composition Measures Are Strongly
          Associated With Diabetic Retinopathy in Indonesian Adults With Type 2 Diabetes.
    LID - dc181074 [pii]
    LID - 10.2337/dc18-1074 [doi]
    AB  - OBJECTIVE: To investigate the associations of estimated resting metabolic rate
          (RMR), body fat (BF), subcutaneous fat (SCF), visceral fat (VF), fat-free mass
          (FFM) percentage, BMI, and waist circumference (WC) with diabetic retinopathy
          (DR) in Indonesian adults with type 2 diabetes. RESEARCH DESIGN AND METHODS: This
          was a community-based cross-sectional study of 1,184 subjects with type 2
          diabetes.
    CI  - (c) 2018 by the American Diabetes Association.
    FAU - Sasongko, Muhammad B
    AU  - Sasongko MB
    AUID- ORCID: http://orcid.org/0000-0002-0366-8335
    AD  - Department of Ophthalmology, Faculty of Medicine, Public Health and Nursing,
          Universitas Gadjah Mada-Rumah Sakit Umum Pusat Dr. Sardjito, Yogyakarta,
          Indonesia mb.sasongko@ugm.ac.id.
    FAU - Widyaputri, Felicia
    AU  - Widyaputri F
    AD  - Department of Ophthalmology, Faculty of Medicine, Public Health and Nursing,
          Universitas Gadjah Mada-Rumah Sakit Umum Pusat Dr. Sardjito, Yogyakarta,
          Indonesia.
    PHST- 2018/05/16 00:00 [received]
    PST - aheadofprint
    SO  - Diabetes Care. 2018 Sep 13. pii: dc18-1074. doi: 10.2337/dc18-1074.


    PMID- 30211195
    OWN - NLM
    STAT- PubMed-not-MEDLINE
    LR  - 20180916
    IS  - 2305-5839 (Print)
    IS  - 2305-5839 (Linking)
    VI  - 6
    IP  - 15
    DP  - 2018 Aug
    TI  - Autologous platelet-rich gel combined with in vitro amplification of bone marrow
          mesenchymal stem cell transplantation to treat the diabetic foot ulcer: a case
          report.
    PG  - 307
    LID - 10.21037/atm.2018.07.12 [doi]
    AB  - The diabetic foot ulcer (DFU) is the leading cause of the high mortality and
          morbidity rates of diabetes patients, and the DFU accounts for approximately 15%
          of all diagnosed diabetes cases in China. Traditional treatment is typically
          ineffective for DFUs.
    FAU - Wu, Qinan
    AU  - Wu Q
    AD  - Endocrine Department, the First Affiliated Hospital of the Third Military Medical
          University (Army Medical University), Chongqing 400038, China.
    PST - ppublish
    SO  - Ann Transl Med. 2018 Aug;6(15):307. doi: 10.21037/atm.2018.07.12.
复制代码目标是提取查询结果里的每篇文章,把他们实列化到类中,类中包含记录里的各个参数
不知道具体应该怎么实现



网友评论:
String a=input.split("-")[0].trim();
if(a.equals("PMID")){
....
}else if......

split 可以切割不同id的论文
但是每个论文内部的参数值要怎么提取到指定的变量里面呢?

比如OWN - NLM 提取成 paper.OWN="NLM"

正则表达式

—— 来自 nubia NX563J, Android 8.1.0上的 v2.0.3
上antlr吧
项目是固定的,项目的顺序也是固定 的,你按固定顺序去处理就行了

还是有不一样的,比如说作者
不同文章作者数不同,导致了au这个参数在每条记录里的重复次数不一样


他应该是按照固定的分隔符展示的吧,直接截取后丢进Map里面,然后用常用的json库把它序列化成json字符串,再反序列化成实体类不就行了?
ps:
出现次数不一样,就弄成Map咯,put之前先get判断原值类型,原值为list就add;原值为string就转换成list,并加入新值;原值不存在就直接put


按“-”切片最大问题就是,AB(abstract)里面的值是不限定内容的,可能大量出现“-”,然后就会和声明参数中“-”混乱。

我想了想最后的思路就按行读取,开头不是缩进的就是某个参数的开头,记录位置,赋值到整数数组中,然后截取数组中两个位置之间的文字。


你不用split整行文本, 只需要用indexOf函数找出第一个‘-’分隔符的index,然后用这个index前后substring就是kv了。
或者你可以用我下面写好的正则表达式, group(1)是key, group(2)是value
    Pattern pattern = Pattern.compile("([A-Z]+) *-(.*?)(?=(?:[A-Z]+ *-)|$)", Pattern.DOTALL)
复制代码

ps: 我去maven库里面搜了一哈, apache下面就有ASN.1的库啊http://mvnrepository.com/artifact/org.apache.directory.api/api-asn1-api




很简单啦。按行读,开始是pmid就是新记录。indexof那个-,然后分割字符串付给自己的结构就行了。

只是解析这种格式的话,应该还用不上语法分析这么硬核的玩法?

感谢 正则还没掌握,用index of 应该最方便

你用indexOf需要先判断跨行缩进的value
没递归结构的就逐行+正则表达式(带捕捉),维护点简单的状态


HashMap paper = new HashMap();
paper.put(input.split("-")[0],input.replace(input.split("-")[0],""));
解析这个问题如果不手撸if else 或者pattern match,有两种主要手段(我知道的)。一种是编译原理那套,直接上antlr; 还有一种是parser combinator模式。

楼主看原文语法复杂度选择,简单的就直接手撸,之后是parser combinator ,最复杂的上antlr

—— 来自 samsung SM-N9500, Android 8.0.0上的 v2.0.3-play


这东西根本不能直接用"-"切割,必须建表,把每个字段前面的都包含进来,
PMID- 30213883 //PMID的头是"PMID-"。
OWN - NLM    // OWN的头是"OWN - "
STAT- Publisher //STAT的头是"STAT- "

每个头都是一行的开始
每个头都占4位,用不完就补空格,后面跟一个减号,一个空格,正则式类似这样:(^[A-Z]{2,4}\\s{0,2}\\-\\s)(.*)


不用正则的话,就直接把“PMID- ”,“OWN - ” 这些串保存在一个静态数组里,把文本用\n split开,将每一行的substring(0, 6)去数组里匹配,匹配到了就是一个新字段,匹配不到就说明是上一个字段文本的继续。遇到空行就是一个新对象。
写了个regex,你得把原来的字符串用\n\n分隔,然后用下面的regex匹配

http://regex101.com/r/ObOBQ8/1

别忘了开启multiline模式 :)

然后你再用正则处理下开头空行就好了