该文本是一系列患者记录的自定义序列化形式。
<PATIENTID>=1231
<PATIENTNAME>=ERICA
<PATIENTHISTORY>=MULTILINE TEXT
<KEYPOINTS>= ASTHMA, HBP, DIABETES
<PATIENTID>=1232
<PATIENTNAME>=NELSON
<PATIENTHISTORY>=MULTILINE TEXT
<KEYPOINTS>= JAUNDICE
我尝试使用以下正则表达式提取它,但它匹配整个字符串而不是每条记录。
const regEx= /^<PATIENTID>=(.)+<PATIENTNAME>=(.)+<PATIENTHISTORY>=(.)+<KEYPOINTS>=(.)+/g;
那么我应该如何改变正则表达式以迭代每条记录并提取相关字段?
答案 0 :(得分:1)
您可以搜索左角和直角与其余部分之间的内容,直到找到不正确的角度,然后获取键和值对。
游乐场:https://regex101.com/r/sf5soM/1
var string = '<PATIENTID>=1231\n<PATIENTNAME>=ERICA\n<PATIENTHISTORY>=MULTILINE TEXT\n<KEYPOINTS>= ASTHMA, HBP, DIABETES\n<PATIENTID>=1232\n<PATIENTNAME>=NELSON\n<PATIENTHISTORY>=MULTILINE TEXT\n<KEYPOINTS>= JAUNDICE',
regex = /<([^>]*)>=([^<]*)/gm,
m,
k, v;
result = [];
while ((m = regex.exec(string)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
[, k, v] = m;
if (k === 'PATIENTID') {
result.push({});
}
result[result.length - 1][k] = v.trim();
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:0)
你可以只为每个数据进行子串。
var str = "<PATIENTID>=1231";
var afterComma = str.substr(str.indexOf("=") + 1);
答案 2 :(得分:0)
/^<PATIENTID>=([\s\S]*?)<PATIENTNAME>=([\s\S]*?)<PATIENTHISTORY>=([\s\S]*?)<KEYPOINTS>=([\s\S]*?)(?=<PATIENTID>|$)/gm
https://regex101.com/r/DpSD1R/4
这里的主要内容是(?:\s|\S)
组,确保您匹配空格和非空格字符......这意味着一切。与.
(点)的区别在于它甚至会匹配换行符,并且您需要它,因为您的某些字段是多行的。
编辑:简化的非捕获组((?:\s|\S)
)与[\s\S]
作为完全成熟的替代品并不是严格需要的。
编辑2:正如@Wiktor指出的,匹配应该在输入结束时或在另一个记录的开头结束。添加了具有正向前瞻(?=<PATIENTID>|$)
的终端条件,也忘记了多行标记
答案 3 :(得分:0)
您可以捕获组^<([^>]+)>
中尖括号之间的名称,然后匹配等号=
,第二部分匹配所有字符,直到您在下一行遇到尖括号模式因为这是新比赛的开始。
这样您也可以匹配MULTILINE TEXT部分中的<>
。
<([^>]+)>=([\s\S]*?(?=^<[^[\r\n>]+>)|[\s\S]*)
解释
<([^>]+)>
捕捉组中的尖括号(捕获组1)=
按字面意思匹配([\s\S]*?
将所有字符匹配为非贪婪的零次或多次(?=^<[^[\r\n>]+>)
断言后面的正面先行是行开头的尖括号模式|
或[\s\S]*
匹配所有字符(您可以将其替换为.*
以仅匹配整个最后一行而不是匹配所有字符)
const regex = /<([^>]+)>=([\s\S]*?(?=^<[^[\r\n>]+>)|[\s\S]*)/gm;
const str = `<PATIENTID>=1231
<PATIENTNAME>=ERICA
<PATIENTHISTORY>=MULTILINE TEXT
< with a line
with a line >
with a <> line
<> with a line
<KEYPOINTS>= ASTHMA, HBP, DIABETES
<PATIENTID>=1232
<PATIENTNAME>=NELSON
<PATIENTHISTORY>=MULTILINE TEXT
and this is a line
and this also
<KEYPOINTS>= JAUNDICE
and this is a line`;
let m, result = [];
while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
if (m[1] === 'PATIENTID') {
result.push({});
}
result[result.length - 1][m[1]] = m[2];
}
console.log(result);
&#13;
答案 4 :(得分:0)
根据我的想法,您可以使用其他一些功能并获得预期的结果。 希望这会有所帮助...
const text = `
<PATIENTID>=1231
<PATIENTNAME>=ERICA
<PATIENTHISTORY>=MULTILINE TEXT
<KEYPOINTS>= ASTHMA, HBP, DIABETES
<PATIENTID>=1232
<PATIENTNAME>=NELSON
<PATIENTHISTORY>=MULTILINE TEXT
<KEYPOINTS>= JAUNDICE
`;
const test = text.replace(/<PATIENT/g, ';').replace(/>=/g, ':').replace(/<KEYPOINTS/g, 'KEYPOINTS').split(';');
const ObjectList = [];
test.map((t) => {
const text = t.trim();
const finalText = text.replace(/\r?\n|\r/g, ';').split(';').map(a => a.trim());
if(finalText) {
finalText.forEach(item => item && ObjectList.push(item));
}
});
console.log(ObjectList);
// output: ["ID:1231",
"NAME:ERICA",
"HISTORY:MULTILINE TEXT",
"KEYPOINTS: ASTHMA, HBP, DIABETES",
"ID:1232",
"NAME:NELSON",
"HISTORY:MULTILINE TEXT",
"KEYPOINTS: JAUNDICE"
]